NOI /2.4基本算法之分治2991:2011

NOI /2.4基本算法之分治2991:2011

2011链接

此题乍一看,嚯哟,直接上手,用个循环不断%10000就搞定,结果来个TLE把俺给整蒙了,结果一细看,嗨呀,不是K小于等于200,是它的位数。如此多的位数那么正常的整型当然存不下咯,那就开个字符数组把它给收了。那么解决了输入的问题还得回到题目关键,那200位多位肯定超时,也无法用变量去存,那么这时候有个看到了一个很神奇的东西,叫%,不断的%的话会不会存在循环?结果我写了一个小东西,康康它是否是我要的。如下:

#include
#include
using namespace std;
int main()
{
    int c=1,bilibili=0;
    while(1)
    {
        bilibili++;
        c*=2011;
        c%=10000;
        if(bilibili!=1&&c==2011){
            cout<<bilibili;
            break;}
    }
}

宁会惊奇的发现它就是500一循环!所以只有求出这个超大的K%500是多少OK,那么问题又来了,这么大的数字,咋个求?想了一阵子终于给俺想出来了:如果它太大,就把它拆了!大伙儿想想,假设有个五位数ABCDE,把它拆成AB000+CDE,AB000是必定能除尽500的,那么CDE%500就是ABCDE%500的答案了(因为可以这样理解%500,就是一直减500,减到最后剩下的数字小于500的时候看看这个数是多少,那么这里就可以理解了,不断的减去500,直到减去了AB000/500个500,那要继续就是看CDE能减500到最后剩下多少了,如果CDE直接小于500那么答案就是直接是CDE了,那么这个过程很显然就等价于CDE%500)。
这样五位数以上的数字都是一个方法,那它来个10000位的咱也不怕呀,何况这才200位,那么如果位数小于10000那自然就可以直接计算了,不必拆开。*可以用atof函数,将字符串变成数字。实现如下:

#include
#include
#include
#include
#include
using namespace std;
char a[201];
int main()
{
    int k;
    cin>>k;
    while(k--)
    {
        cin>>a;
        int len=strlen(a);
        if(len>=5)
        {
            int u=(a[len-3]-'0')*100+(a[len-2]-'0')*10+(a[len-1]-'0'),c=1;
            u%=500;
            for(int i=0;i<u;++i)
            {
                c*=2011;
                c%=10000;
            }
            cout<<c<<endl;
        }
        else
        {
            int u=atof(a),c=1;
            for(int i=0;i<u;++i)
            {
                c*=2011;
                c%=10000;
            }
            cout<<c<<endl;
        }
    }
}

你可能感兴趣的:(NOI /2.4基本算法之分治2991:2011)