Educational Codeforces Round 90 (Rated for Div. 2)
Donut Shops
題意:兩家貨店,一家a元一件,一家b件c元,求買多少到第一家絕對划算,買多少到第二家絕對划算,
考慮 b ==1時,直接判斷平均單價即可。
當 第一個的平均單價小於第二個的平均單價,第一個絕對優勢,因為可以拆開賣。
第一個的平均單價等於第二個的平均單價,c只會 > a
沒有相等情況
第一個的平均單價大於於第二個的平均單價 且a>=c 第一個沒戲
a<c 買一件第一個滿足,
#include<bits/stdc++.h> usingView Codenamespace std; const int N=6e2+500; typedef long long ll; int main(){ int t;scanf("%d",&t); while(t--){ ll a,b,c,ans1=0,ans2=0; cin>>a>>b>>c; // scanf("%lld %lld %lld",&a,&b,&c); double p1=a*1.0,p2=c*1.0/b; if(b==1){if(p1==p2)ans1=ans2=-1; else if(p1>p2)ans1=-1,ans2=1; else ans1=1,ans2=-1; } else { if(p1<p2){ ans1=1,ans2=-1; } else if(p1==p2){ if(a>c)ans1=-1,ans2=b; else if(a<c)ans1=1,ans2=-1; } else if(p1>p2){ if(a<c)ans1=1,ans2=b; else if(a>c)ans1=-1,ans2=b; else if(a==c)ans1=-1,ans2=b; } } cout<<ans1<<" "<<ans2<<endl; // cout<<ans1<<" "<<ans2<<endl; } // system("pause"); return 0; }
01 Game
無腦題,暴力刪除
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main(){ int t; scanf("%d",&t); while(t--){ string s; cin>>s; int cnt=0; while(1){ int len=s.size(); bool flag=0; for(int i=0;i<len;i++){ if(i!=len-1&&s[i]!=s[i+1]){ flag=1; cnt++; s.erase(i,2); break; } } if(!flag)break; } if(cnt%2)puts("DA"); else puts("NET"); } // system("pause"); return 0; }View Code
Pluses and Minuses
給出一段程式碼,要求模擬虛擬碼過程,直接模擬TLE,觀察程式碼效果
對於一個給定的只含 + - 字串,由0開始列舉一個step,遇 + 則+ ,遇 - 則 - ,小於0就退出;答案為所有步數的和。
暴力列舉O(n^n),考慮如下做法:
從左到右列舉,遇到0就加上這個步數,然後cnt清零,最後走完加一個len。
實際上在cur<0的時候,必然會列舉到一個點進過,加上這個距離。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main(){ int t;scanf("%d",&t); while(t--){ string s; cin>>s; ll ans=0,cur=0; int len=s.size(); for(int i=0;i<len;i++){ if(s[i]=='+')cur++; else cur--; if(cur<0){ ans+=i+1; cur=0; } } ans+=len; cout<<ans<<endl; } // system("pause"); return 0; }View Code
Maximum Sum on Even Positions
題意:對於一個給定的序列,可以旋轉一個子區間,求偶數項和最大。下標從0開始。
首先考慮 旋轉長度為奇數沒有意義,
旋轉長度為偶數時: 1 , 首項為偶項:
翻轉每個奇項對答案貢獻為 a(i+1) - ai 求一個最大連續和。
2, 首項為奇項:
翻轉每個奇項對答案貢獻為 ai- a(i+1) 求一個最大連續和。
二者取大
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+50; ll a[N]; int main(){ int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); ll maxx=0,sum1=0,sum2=0,ans=0; for(int i=0;i<n;i++){ cin>>a[i]; if(!(i%2))ans+=a[i]; } for(int i=1;i<n;i+=2){ if(i<n-1)sum1=max(0ll,sum1+a[i]-a[i+1]); maxx=max(maxx,sum1); } for(int i=0;i<n;i+=2){ if(i<n-1)sum2=max(0ll,sum2+a[i+1]-a[i]); maxx=max(maxx,sum2); } // cout<<"ans :"; cout<<maxx+ans<<endl; } // system("pause"); return 0; }View Code
Sum of Digits
題意 給定一個n,k 。 求一個 x 使得 f(x)+f(x+1)+⋯+f(x+k)=nf(x)+f(x+1)+⋯+f(x+k)=n.
f(x)為十進位制的數字和。
考慮k<=9 那麼進位最多一次。
不進位的情況下:f(x+1)=f(x)+1. 進位實際上減去若干個9 。
設有 t 個受進位影響。影響的9的個數為 i 。
那麼有 (k+1) f(x) +k *(k+1)/ 2 - 9 * t * i = n
考慮 t 實際上 受列舉x的個位影響,那麼實際上列舉 x 的 個位 和 i 即可 推出 f(x)
對於一個給定的f (x)要求 i 個9受到影響,x要最小,貪心構造即可。
複雜度O (40)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll inf=2e18; ll cur,n,k,ans; bool build(ll fx,ll i,ll x){ vector<ll>v; v.push_back(x);fx-=x; if(fx<0)return 0; for(int p=1;p<i;p++){ fx-=9; if(fx<0)return 0; v.push_back(9); } if(fx>=8){fx-=8;v.push_back(8);} while(fx>=9){fx-=9;v.push_back(9);} if(fx>0)v.push_back(fx); cur=0; ll cnt=1; for(int p=0;p<v.size();p++){ cur+=v[p]*cnt; cnt*=10; } // if(x==4)cout<<"path : "<<cur<<endl; return 1; } int main(){ int t;scanf("%d",&t); while(t--){ scanf("%lld %lld",&n,&k); ll t,fx; n-=k*(k+1)/2; // cout<<"ans : "; if(n<0){cout<<-1<<endl;continue;} ans=inf; for(ll x=0;x<=9;x++){ if(x+k>=10)t=(x+k)%10+1; else t=0; for(ll i=1;i<=30;i++){ if((n+9*t*i)%(k+1))continue; fx=(n+9*t*i)/(k+1); if(fx<x)continue; // if(x==4&&t==2)cout<<"yes"<<endl; if(!build(fx,i,x)){ // cout<<"false"<<endl; continue; } // cout<<"true"<<endl; ans=min(ans,cur); } } if(ans!=inf)printf("%lld\n",ans); else printf("-1\n"); } // system("pause"); return 0; }View Code
Network Coverage
題意 n 個村莊構成一個環,每個村莊要求 ai,每兩個村莊有一個站bi, 問是否可以滿足每個村莊 ai 的需要。
最大流水不過
考慮第一個站,分配給第一個村莊x,剩下的貪心構造,滿足上面的,剩下的全給下面的,然後從第n個村莊留下來的為c,
那麼分配給第一個村莊實際上為 f (x)= x + c
考慮 x 減少 1 ,實際 c 增加小於1,f ( x ) 隨著 x 減小而減小,滿足單調性。
x增大,c減小,f(x)增大,求得一個c>=0 的 x 的最大解,直接二分即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int N=1e6+60; int n; ll a[N],b[N]; ll check(ll x){ ll out=b[1]-x,need,pos; need=a[2]-out; for(int i=2;i<=n;i++){ // if(i==n)pos= need=a[i]-out; if(need<0)need=0; out=b[i]-need; if(out<0)return -1ll; } return out; } int main(){ int t;scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)scanf("%d",&b[i]); ll l=0,r=b[1]; while(l<=r){ ll mid=(l+r)/2; if(check(mid)>=0){ l=mid+1; } else r=mid-1; } if(r<0)puts("NO"); else if(check(r)+r>=a[1])puts("YES"); else puts("NO"); } // system("pause"); return 0; }View Code