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

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值