NOI 2991:2011(思维/规律)

来源:互联网 发布:高中化学知识网络结构 编辑:程序博客网 时间:2024/06/05 06:14
总时间限制: 
1000ms 
内存限制: 
65536kB
描述
已知长度最大为200位的正整数n,请求出2011^n的后四位。
输入
第一行为一个正整数k,代表有k组数据,k<=200接下来的k行,

每行都有一个正整数n,n的位数<=200
输出
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0
样例输入
3528792
样例输出
1051815521


这可是200位,不是200,所以只能字符串输入(开始漏了),先打个表,将其10以内的次数存到数组s,然后再将10次、100次,1000次……继续打个表数组d;然后想着对其每一位tmp处理,个位的话直接*s[tmp],否则* pow(d[cnt],tmp,10000)(即2011^(10*cnt) == 2011^10^cnt),然后取模输出就行了。
200位的话,首先考虑打表找规律,然而我的表打得有点小,没找到,发现提问区好多找规律出来的。

oi题做着感觉挺好啊,和cf有点类似,虽然这个题的标题是分治

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;char str[205];int s[25] = {1},d[205] = {1};inline int pow(int a,int b,int p){    int r = 1,base = a;    while(b)    {        if(b&1)            r = r*base%p;        base = base*base%p;        b >>= 1;    }    return r%p;}int main(){    int p = 2011;    for(int i = 1;i <= 15;i++)    {        s[i] = pow(p,i,10000);        //printf("%d\n",p);    }    p = s[10];    for(int i = 1;i <= 202;i++)    {        d[i] = p % 10000;        p = pow(p,10,10000) % 10000;    }    int k,n;    cin >> k;    while(k--)    {        scanf("%s",str);        int len = strlen(str);        int ans = 1,cnt = 0;        for(int i = len-1;i >= 0;i--)        {            int tmp = str[i]-'0';            if(cnt == 0)                ans = ans * s[tmp] % 10000;            else                ans = ans * pow(d[cnt],tmp,10000) % 10000;            cnt++;        }        printf("%d\n",ans);    }    return 0;}



0 0