GMOJ 4222. 恐怖的奴隶主 题解
思路
开始以为是 【清华集训2015】恐怖的奴隶主 ,心态差点炸裂。
题目思路比较诡异。
考虑模拟样例:
1|2|3
------
1
1|2|3
------
1|1
1|2|3
------
1|1|2
1|2|3
------
1|2|3
1|2|3
------
2|3|1
接下来新加入的数量与上一次弹出的数量一样,于是就循环了。
这个队列长度显然是 \(m+1\) ,而其中非零项数仅为 \(\log k\) .
那么我们暴力求出有数字的部分,如果数量大于 \(m+1\) ,那么取后 \(m+1\) 项组成循环,否则往前补 0 直到长度为 \(m+1\) .
对于 \(m \le 2\) 和一些其他的边界情况需要特判。
CODE
#include<cstdio>
#include<iostream>
#define reg register
#define ll long long
using namespace std;
const int N=1010,FSIZE=256;
ll n,m,k,num[N];
char BuF[FSIZE],*InF=BuF;
template<typename T>void read(T &x){
for(;47>*InF||*InF>58;++InF);
for(x=0;47<*InF&&*InF<58;x=x*10+(*InF++^48));
}
int main(){
fread(BuF,1,FSIZE,stdin);
read(n);read(m);read(k);
if((k==1||m==1)&&n>=m){
printf("0");
return(0);
}
if(k==1||m==2){
printf("1");
return(0);
}
ll sum=num[0]=1,rod=0;
for(;sum+sum<=k&&n;--n){
num[++rod]=min(k-sum,sum);
sum+=min(k-sum,sum);
if(rod+1>=m){
sum-=num[rod+1-m];
}
}
if(!n){
if(rod+1>=m){
sum+=num[rod+1-m];
}
printf("%lld",sum);
return(0);
}
n%=(m+1);
if(n+rod<m){
printf("%lld",k);
}else{
printf("%lld",k-num[n+rod-m]);
}
return(0);
}

浙公网安备 33010602011771号