这个是前几天作的比赛,因为今晚上还有CF所以就把前几天写的东西总结一下。
460A 直接模拟题意,不过我在作的过程中一直担心余数会对结果产生影响。
#include<iostream> #include<cstdio> using namespace std; int main() { int n,m; cin>>n>>m; for(int i=n;;i++) { if(n+i/m==i) { printf("%d\n",i); break; } } return 0; }
460 B 其实也是一个模拟题,不过由于数据量比较大,所以你得转化一下思路,要不然肯定会超时,x?=?b·s(x)a?+?c,?
由于是s(x)代表的是各个位数的和,所以你可以从它为出发点来找到符合题意的x,想到这一点就变得很简单了。
#include<iostream> #include<cstdio> #define maxn 600005 using namespace std; __int64 w[maxn]; int main() { __int64 i; __int64 a,b,c; cin>>a>>b>>c; int t=0; for(__int64 i=1; i<=99; i++) { __int64 x=1; __int64 sum=0; for(int m=1; m<=a; m++) x*=i; x*=b; x+=c; __int64 u=x; while(u) { sum+=u%10; u/=10; } if(sum==i&&x>0&&x<=1000000000) w[t++]=x; } cout<<t<<endl; if(t>0) { for(int j=0; j<t-1; j++) cout<<w[j]<<" "; cout<<w[t-1]<<endl; } else ; return 0; }
460c 其实题意是很好理解的,我当时的第一反应就是要用数据结构作,每一次都要统计,然后选出那个最小值最
多的那一段进行种植,然后试了试树状数组,结果由于好几个地方不知道怎么变化,暴力给写了下,果断在第八个样
例那里就给T了,哎,然后就想不出来啥好办法了。
最后看了下别人的代码,竟然是二分给做的,我在想二分竟然能做吗?
然后看了好久的代码,才慢慢理解了,只能说他们太屌了。
归结起来,其实我觉得难的地方有两点:一是你要理解这个题它所要的最终状态是什么?二是处理二分的几个比
较重要的细节。
#include<map> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> #define pi acos(-1.0) #define inf 0xfffffff #define maxn 200110//不理解,为啥题目给的是1e5,我开到10010在第十五组样例会wa,改大点就行了。求解释? using namespace std; __int64 a[maxn],b[maxn]; int n,m,w; int solve(__int64 mid) { __int64 sum=0; __int64 ans=0; memset(b,0,sizeof(b)); for(int i=0; i<n; i++) { sum+=b[i]; if(sum+a[i]<mid) { ans+=mid-(sum+a[i]);//需要更新每一段的值,如果它大于更新的次数的话,就说明不行。 if(ans>(__int64)(m)) return 0; b[i+w]-=mid-(sum+a[i]);//用来统计到下一段的开始的时候要减去上一段增加的值。 sum+=mid-(sum+a[i]); } } return 1; } int main() { scanf("%d%d%d",&n,&m,&w); __int64 minn=9999999999; for(int i=0; i<n; i++) { scanf("%I64d",&a[i]); minn=min(minn,a[i]); } __int64 left,right,mid; left=1,right=minn+m;//最大的可能就是让最小的值连续增加m。 while(left<=right) { mid=(left+right)>>1; if(solve(mid)) left=mid+1; else right=mid-1; } printf("%I64d\n",right); return 0; }
时间: 2024-11-07 14:45:12