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;
}
哦,,我之前生成质数的那个都写错了,,,
。。。诶。。。。。。。。调了好久