Codeforces Round #601 (Div. 2)node
题意:有T组数据,每组数据给两个数a和b,每次能够对a进行(-5,-2,-1,+1,+2,+5)操做中的一种,问从a转换为b最少须要多少次。c++
思路:贪心,对a和b的差取绝对值,先尽量多的选操做5,再尽量多的选操做2,最后再选操做1 .数组
#include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int total,a,b; int num[3]={5,2,1}; cin>>total; while(total--){ cin>>a>>b; long long cha=abs(a-b); int ans=0; if(cha>0){ for(int i=0;i<3;i++){ ans+=cha/num[i]; cha%=num[i]; } } cout<<ans<<endl; } return 0; }
题目数据范围被修改了,如今改成了m≤n,就很好写了spa
题意:给n个点,让建m条边,要求每一个点至少有2个临边,建边的费用为边的两个顶点之和,问可否建出该图,若是能输出最小建造费用,不然输出-1.code
思路:造成环便可,m<n和n=2时不知足要求。(这是原题目:m>n时的思路和证实:传送 )orm
#include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int total,n,m,get_num; cin>>total; while(total--){ cin>>n>>m; int ans=0; for(int i=1;i<=n;i++){ cin>>get_num; ans+=get_num; } if(n==2 || m<n){ cout<<-1<<endl; }else{ ans*=2; cout<<ans<<endl; for(int i=1;i<=n;i++){ int j=(i+1>n?1:i+1); cout<<i<<" "<<j<<endl; } } } return 0; }
题意:有一串序列,好比[1,4,2,3,5],给出它每三个数字的排序{[1,4,2],[4,2,3],[2,3,5]},如今将其打乱,大分组顺序和小份内组顺序均可能会变化如变为:blog
{[2,4,3],[1,2,4],[5,3,2]},如今给出被打乱后的序列,请输出它对应的任意一组可能的顺序序列
思路:开始和结尾的数只会出现一次,找到开始和结尾,而后能够肯定开始的那一组,以后每两个数都能肯定第三个数,用map作一下便可。
(我是unordered_map套了vector,初始化每组数中每两个数作一次key,第三个数做为值塞入对应key的vector中,后面判断总的大数组中相邻的数对应key的vector的size为2,间隔数对应key的vector的size为1)
#include<bits/stdc++.h> using namespace std; int book[100005]; vector<int>ans; unordered_map<long long,vector<int> >tree; vector<int>null_vec; struct node{ int a,b,c; }que[100005]; void solve(int a,int b,int c){ long long xiao=1LL*min(a,b); long long da=1LL*max(a,b); long long key=xiao*1000000+da; if(tree.find(key)==tree.end()){ tree[key]=null_vec; tree[key].push_back(c); }else{ tree[key].push_back(c); } } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n,a,b,c; cin>>n; memset(book,0,sizeof(book)); for(int i=1;i<=n-2;i++){ cin>>a>>b>>c; que[i].a=a;que[i].b=b;que[i].c=c; solve(a,b,c); solve(a,c,b); solve(b,c,a); book[a]++; book[b]++; book[c]++; } int start,k1,k2,end_p,gg; for(int i=1;i<=n;i++){ if(book[i]==1){ start=i; gg=i+1; break; } } for(int i=gg;i<=n;i++){ if(book[i]==1){ end_p=i; break; } } for(int i=1;i<=n;i++){ if(que[i].a==start){ k1=min(que[i].b,que[i].c); k2=max(que[i].b,que[i].c); break; }else if(que[i].b==start){ k1=min(que[i].a,que[i].c); k2=max(que[i].a,que[i].c); break; }else if(que[i].c==start){ k1=min(que[i].a,que[i].b); k2=max(que[i].a,que[i].b); break; } } ans.push_back(start); while(ans.size()+3<n){ long long key=1LL*k1*1000000+1LL*k2; int num1=tree[key][0]; int num2=tree[key][1]; int type=0; int kk1,kk2; if(num1==start){ kk1=min(k2,num2); kk2=max(k2,num2); type=1; }else if(num2==start){ kk1=min(k2,num1); kk2=max(k2,num1); type=2; } long long nk=1LL*kk1*1000000+1LL*kk2; if(tree[nk].size()==1){ swap(k1,k2); if(type==1){ kk1=min(k2,num2); kk2=max(k2,num2); }else if(type==2){ kk1=min(k2,num1); kk2=max(k2,num1); } } ans.push_back(k1); start=k1;k1=kk1;k2=kk2; } long long gk1=min(start,k1); long long gk2=max(start,k1); long long ggkey=gk1*1000000+gk2; if(tree[ggkey].size()==1){ swap(k1,k2); } for(int i=0;i<ans.size();i++){ cout<<ans[i]<<" "; } cout<<k1<<" "<<k2<<" "<<end_p<<endl; return 0; }
题意:r×c大小的农场养k只鸡,有些单位格上有米粒,如今给鸡分配空间,要求:每一个鸡至少获得一个单位格,每只鸡的活动区域要4联通,本身的区域不能分开,得到米粒最多的鸡和得到米粒最少的鸡的米粒差尽量小。
思路:S型给鸡分配场地便可,扫描得总米粒数为x,有x%k只鸡吃x/k+1粒米,有k-x%k只鸡吃x/k粒米,(我不知道整除时怎么放入总状况因此单独写了一遍整除时的,因此代码比较长(裂开))。
#include<bits/stdc++.h> using namespace std; char ditu[105][105]; char ans[105][105]; int t,r,c,k; int every_l,every_h,cont_h,cont_l; string biao="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; void solve0(){ int ct_h=0,ct_l=0; for(int i=0;i<r;i++){ if(i%2==0){ for(int j=0;j<c;j++){ if(ditu[i][j]=='R'){ ans[i][j]=biao[ct_h]; ct_h++; }else{ if(ct_l<cont_l){ ans[i][j]=biao[cont_h+ct_l]; ct_l++; }else{ if(i==0){ ans[i][j]=ans[i][j-1]; }else ans[i][j]=ans[i-1][j]; } } } }else{ for(int j=c-1;j>=0;j--){ if(ditu[i][j]=='R'){ ans[i][j]=biao[ct_h]; ct_h++; }else{ if(ct_l<cont_l){ ans[i][j]=biao[cont_h+ct_l]; ct_l++; }else{ ans[i][j]=ans[i-1][j]; } } } } } return; } void solve(){ int ct_h=0,ct_l=0,cont_mi=0; for(int i=0;i<r;i++){ if(i%2==0){ for(int j=0;j<c;j++){ if(ditu[i][j]=='R'){ cont_mi++; if(ct_h==cont_h){//is small if(cont_mi>every_l){ cont_mi=1; ct_l++; ans[i][j]=biao[cont_h+ct_l]; }else{ ans[i][j]=biao[cont_h+ct_l]; } }else{//is big if(cont_mi<every_h){ ans[i][j]=biao[ct_h]; }else{ cont_mi=0; ans[i][j]=biao[ct_h]; ct_h++; } } }else{ if(ct_h==cont_h){ if(cont_l==0) ans[i][j]=biao[cont_h-1]; else ans[i][j]=biao[cont_h+ct_l]; }else{ ans[i][j]=biao[ct_h]; } } } }else{ for(int j=c-1;j>=0;j--){ if(ditu[i][j]=='R'){ cont_mi++; if(ct_h==cont_h){//is small if(cont_mi>every_l){ cont_mi=1; ct_l++; ans[i][j]=biao[cont_h+ct_l]; }else{ ans[i][j]=biao[cont_h+ct_l]; } }else{//is big if(cont_mi<every_h){ ans[i][j]=biao[ct_h]; }else{ cont_mi=0; ans[i][j]=biao[ct_h]; ct_h++; } } }else{ if(ct_h==cont_h){ if(cont_l==0) ans[i][j]=biao[cont_h-1]; else ans[i][j]=biao[cont_h+ct_l]; }else{ ans[i][j]=biao[ct_h]; } } } } } return; } int main() { scanf("%d",&t); while(t--){ int rice=0; scanf("%d %d %d\n",&r,&c,&k); for(int i=0;i<r;i++){ scanf("%s",ditu[i]); for(int j=0;j<c;j++){ if(ditu[i][j]=='R') rice++; } } every_l=rice/k,every_h=every_l+1,cont_h=rice%k,cont_l=k-cont_h; if(every_l==0) solve0(); else solve(); for(int i=0;i<r;i++){ for(int j=0;j<c;j++){ printf("%c",ans[i][j]); } printf("\n"); } } return 0; }
E1. Send Boxes to Alice (Easy Version)
题意:一行有n个盒子,每一个盒子有1个或没有巧克力,每次操做能够将第i个盒子中的一个巧克力放入第i-1或者第i+1个盒子中(盒子存在),问最少操做几回,最后全部有巧克力的盒子中的巧克力数能被k整除
思路:先分解质因数,由于是easy版本因此对于每一个质因子pr,每pr个有巧克力的盒子分为一组,枚举放入每个盒子的操做数取和的最小值便可,优化一下前缀后缀暴力就能过。
#include<bits/stdc++.h> using namespace std; vector<int>que; long long solve(int pr) { long long sum=0;//will return the value; for(int st=0;st<que.size();st+=pr){ long long ans=0; for(int i=1;i<pr;i++){ ans+=que[st+i]-que[st]; } long long l=0,r=pr-1,zuo=0,you=ans; for(int i=1;i<pr;i++){ l+=1; zuo+=l*(que[st+i]-que[st+i-1]); you-=r*(que[st+i]-que[st+i-1]); r--; ans=min(ans,zuo+you); } sum+=ans; } return sum; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n,get_num; cin>>n; for(int i=1;i<=n;i++){ cin>>get_num; if(get_num>0){ que.push_back(i); } } if(que.size()<=1){ cout<<-1<<endl; }else{ long long ans=10000000000000000; vector<int>prime; int size_p=que.size(); prime.push_back(size_p); for(int pr=2;pr*pr<=size_p;pr++){ bool flag=false; while(size_p%pr==0){ flag=true; size_p/=pr; } if(flag)prime.push_back(pr); } if(size_p>1)prime.push_back(size_p); for(int i=0;i<prime.size();i++){ ans=min(ans,solve(prime[i])); } cout<<ans<<endl; } return 0; }
E2. Send Boxes to Alice (Hard Version)
题意:如E1,只是每一个盒子中巧克力个数Ai范围改成[0,1e6]
思路:仍是先分解质因数,对于一个数Ai,假设当前的质因数为pr,这个位置要知足能被k整除,有两个可能,要么是它日后面搬运pr%k石子,要么是后面往它搬运k−pr%k个石子。
对于每个Ai知足后,由于只会对下一个位置产生影响,因此下一个位置Ai+1算上Ai产生的影响,以后又是一个新的子问题。
最后的答案为:对于每个质因数pr,求每位置i求min(pre[i],pr−pre[i])的和,最后全部和中的最小值及为答案。
#include<bits/stdc++.h> using namespace std; int num[1000005]; long long solve(long long pr,int n){ long long pre=0,ans=0; for(int i=1;i<=n;i++){ pre=(pre+num[i])%pr; ans+=min(pre,pr-pre); } return ans; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n; long long sum=0,ans=1e18; cin>>n; for(int i=1;i<=n;i++){ cin>>num[i]; sum+=num[i]; } if(sum<=1){ cout<<-1<<endl; return 0; } for(long long pr=2;pr*pr<=sum;pr++){ bool flag=false; while(sum%pr==0){ flag=true; sum/=pr; } if(flag) ans=min(solve(pr,n),ans); } if(sum>1) ans=min(solve(sum,n),ans); cout<<ans<<endl; return 0; }
不会搞,23333