这个是前几天作的比赛,因为今晚上还有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;
}