[NOIP模拟][费马小定理][高精度]

来源:互联网 发布:手机网络ip地址查询 编辑:程序博客网 时间:2024/06/07 13:35

T1细胞分裂

【问题描述】
小A 养了一大坨细胞。
最初小A 只有1 个细胞。每秒,小A 的每个细胞都会分裂成2 个细胞。
已知:现在离“最初”已经过去了x 秒,那么现在的细胞数当然是可以计算的。
小A 想知道的当然不是当前的细胞数。小A 知道他养的细胞的习性:每y
个细胞会聚成一团。经常会有剩下的细胞,那么我们称这些细胞是孤独的。
小A 想知道的就是孤独的细胞个数。
【输入文件】
输入文件为cell.in。
输入文件共一行,为两个整数x y,以空格隔开。
【输出文件】
输出文件为cell.out。
输出文件共一行,为一个整数,即孤独的细胞个数。
【输入样例】
3 3
【输出样例】
2
【数据规模和约定】
对于10%的数据,x<2^6。
对于20%的数据,x<2^17。
对于40%的数据,x<2^64。
对于70%的数据,x<2^2333。
对于100%的收,0≤x<2^233333,y 是3 到1000 之间(含两端)的质数

解题思路:显然2^x%y
But,,x巨大,又因为y是质数,那么就想到了费马小定理
(a^p-1)%p=1,,a,p互质。
然后我很愚蠢的用了高精度,而且还是最复杂的那种高精度,,,,
可以读了一位一位模,也可以用高精度模,然而我减了一遍,乘了一遍,除了一遍。,WTF。。

代码

#include<iostream>#include<cstdio>#include<ctime>#include<cstdlib>#include<cmath>#include<cstring>#include<string>#include<set>#include<map>#include<vector>#include<queue>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endif#define INF 0x3f3f3f3f#define clock CLOCKS_PER_SEC#define cle(x) memset(x,0,sizeof(x))#define maxcle(x) memset(x,127,sizeof(x))#define mincle(x) memset(x,-1,sizeof(x))#define cop(a,x) memcpy(x,a,sizeof(a))#define FROP "cell"#define C(a,b) next_permutation(a,b)#define LL long long#define smin(x,tmp) x=min(x,tmp)using namespace std;const int N = 75000;int y,p;char s[N];struct bigint {    static const int P=1,M=10;    int w[N];    bigint(){cle(w);w[0]=1;}    void readin()    {         int now=1,ct=0,c1=1;         for(int i = strlen(s)-1; i>=0; i--)         {             w[now]=(s[i]-'0')*c1;             c1*=10;             ct++;             if(ct==P&&i){now++;ct=0;c1=1;}         }         w[0]=now;    }    bigint operator *(const int b) const     {        bigint a=*this,c;        int& len=c.w[0];        int tmp=b,qq=0;            while(tmp)qq++,tmp/=10;        len=a.w[0]+qq;        for(int i=1;i<=len;i++)        {            c.w[i]+=a.w[i]*b;            if(c.w[i]>=M)            {                c.w[i+1]+=c.w[i]/M;                c.w[i]%=M;            }        }        while(c.w[len])        {            c.w[len+1]+=c.w[len]/M;            c.w[len++]%=M;        }        while(!c.w[len]&&len>1)len--;        return c;    }    bigint operator / (const int b)const    {        bigint a=*this,c;        int& len=c.w[0];        len=a.w[0];        int tmp=0;        for(int i = len; i >= 1; i--)        {            tmp+=a.w[i];            if(tmp>=b)            {                c.w[i]+=tmp/b;                tmp%=b;            }            tmp*=M;        }        while(!c.w[len]&&len>1)len--;        return c;    }    bigint operator - (const bigint &b)const     {        bigint a=*this;        int& len=a.w[0];        len=a.w[0];        int borrow=0;        for(int i = 1; i <= len ; i++)        {            a.w[i]-=b.w[i];            while(a.w[i]<0)            {                a.w[i]+=M;                borrow++;            }            a.w[i+1]-=borrow;            borrow=0;        }        while(!a.w[len]&&len>1)len--;        return a;    }    bool operator < (const bigint &b) const     {        bigint a=*this;        if(a.w[0]^b.w[0])return a.w[0]<b.w[0];        for(int i=a.w[0];i>=1;i--)        {            if(a.w[i]^b.w[i]) return a.w[i]<b.w[i];        }        return false;    }    bool operator > (const bigint &b)const{return b<*this;}    bool operator >=(const bigint &b)const{return !(*this<b);}    bool operator <=(const bigint &b)const{return !(b<*this);}    bool operator !=(const bigint &b)const{return b<*this||*this<b;}    bool operator ==(const bigint &b)const{return !(b<*this)&&!(*this<b);}}a,b,c,pp;int print(){    int tmp=c.w[c.w[0]],c1=10;    for(int i = c.w[0]-1; i>=1; i--)        tmp=(c1*tmp)+c.w[i];    return tmp;}int kmi(int x){    if(x==0)return 1;    if(x==1)return 2;    LL tmp=kmi(x/2)%p;    if(x%2)return (tmp*tmp*2)%p;    return (tmp*tmp)%p;}int main(){    freopen(FROP".in","r",stdin);    freopen(FROP".out","w",stdout);    cle(s);    scanf("%s",s);    a.readin();    scanf("%d",&p);    b=a/(p-1);    b=b*(p-1);    c=a-b;    y=print();    int ans=kmi(y);    printf("%d\n",ans);    return 0;}

其实最后也可以不用快速幂,诶,,,,写了一个最复杂的,就当练手高精度吧,。。。。调试的我也很伤心。

给一个对拍的代码吧,,对拍打法好。,,,膜拜ORZ

【datamack】

#include<iostream>#include<cstdio>#include<ctime>#include<cstdlib>#include<cmath>#include<cstring>#include<cstdlib>#include<ctime>#include<string>#include<set>#include<map>#include<vector>#include<queue>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endif#define INF 0x3f3f3f3f#define clock CLOCKS_PER_SEC#define cle(x) memset(x,0,sizeof(x))#define maxcle(x) memset(x,127,sizeof(x))#define mincle(x) memset(x,-1,sizeof(x))#define cop(a,x) memcpy(x,a,sizeof(a))#define FROP "cell"#define C(a,b) next_permutation(a,b)#define LL long long#define smin(x,tmp) x=min(x,tmp)using namespace std;const int p[200]={0,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997};int main(){    freopen("cell.in","w",stdout);    srand(time(0));    int x=rand()%10000000+1;    int y=rand()%167+1;    printf("%d %d",x,p[y]);    return 0;}

【plain】

#include<iostream>#include<cstdio>#include<ctime>#include<cstdlib>#include<cmath>#include<cstring>#include<cstdlib>#include<ctime>#include<string>#include<set>#include<map>#include<vector>#include<queue>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endif#define INF 0x3f3f3f3f#define clock CLOCKS_PER_SEC#define cle(x) memset(x,0,sizeof(x))#define maxcle(x) memset(x,127,sizeof(x))#define mincle(x) memset(x,-1,sizeof(x))#define cop(a,x) memcpy(x,a,sizeof(a))#define FROP "std"#define C(a,b) next_permutation(a,b)#define LL long long#define smin(x,tmp) x=min(x,tmp)using namespace std;LL x;int p;int kmi(LL x){    if(x==0)return 1;    if(x==1)return 2;    LL tmp=kmi(x/2)%p;    if(x%2)return (tmp*tmp*2)%p;    return (tmp*tmp)%p;}int main(){    freopen("cell.in","r",stdin);    freopen("std.out","w",stdout);    scanf("%d%d",&x,&p);    int ans=kmi(x);    printf("%d",ans);    return 0;}

哦,,我之前生成质数的那个都写错了,,,
。。。诶。。。。。。。。调了好久

0 0
原创粉丝点击