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);
}
posted @ 2021-06-12 15:38  ToUNVRSe  阅读(110)  评论(0)    收藏  举报