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