Donut Shops
题意:两家货店,一家a元一件,一家b件c元,求买多少到第一家绝对划算,买多少到第二家绝对划算,
考虑 b ==1时,直接判断平均单价即可。
当 第一个的平均单价小于第二个的平均单价,第一个绝对优势,因为可以拆开卖。
第一个的平均单价等于第二个的平均单价,c只会 > a
没有相等情况
第一个的平均单价大于于第二个的平均单价 且a>=c 第一个没戏
a<c 买一件第一个满足,
#include<bits/stdc++.h> using namespace 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; }
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; }
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; }
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 ",ans); else printf("-1 "); } // system("pause"); return 0; }
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; }