題目大意就是說:有棵樹,每個節點有k個兒子,能算出這棵樹最小的深度D,使得這個深度的節點數對p取模的結果就是N?
,注意這裏是對p取模之後的結果就是N,也就是說N<=p-1&&N>=0,這個就是這道題的陷阱,需要注意。
輸入的順序是k,p,N.(1<=k,p,N<=10^9)
輸出的時候如果沒有解,那麼直接輸出"Orz,I can’t find D!",沒有引號。
下邊代碼實現:
全都是模板:
#include<iostream>
#include<cmath>
#include<cstdio>
#define MAXX 65535
using namespace std;
struct hash
{
int a,b,next;
}Hash[MAXX<<1];
int flag[MAXX+66];
int top,idx;
void ins(int a,int b)
{
int k=b&MAXX;
if(flag[k]!=idx)
{
flag[k]=idx;
Hash[k].next=-1;
Hash[k].a=a;
Hash[k].b=b;
return;
}
while(Hash[k].next!=-1)
{
if(Hash[k].b==b)return;
k=Hash[k].next;
}
Hash[k].next=++top;
Hash[top].next=-1;
Hash[top].a=a;
Hash[top].b=b;
}
int find(int b)
{
int k=b&MAXX;
if(flag[k]!=idx)return -1;
while(k!=-1)
{
if(Hash[k].b==b)return Hash[k].a;
k=Hash[k].next;
}
return -1;
}
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int ex_gcd(int a,int b,int &x,int &y)
{
if(!b){x=1;y=0;return a;}
int d=ex_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int inval(int a,int b,int n)
{
int x,y,e;
ex_gcd(a,n,x,y);
e=(long long)x*b%n;
return e<0?e+n:e;
}
int pow(long long a,int b,int c)
{
long long ret=1%c;
a%=c;
while(b)
{
if(b&1)ret=ret*a%c;
a=a*a%c;
b>>=1;
}
return ret;
}
int Baby(int a,int b,int c)
{
top=MAXX;++idx;
long long buf=1%c,D=buf,k;
int i,d=0,tem;
for(i=0;i<=100;buf=buf*a%c,++i)
if(buf==b)return i;
while((tem=gcd(a,c))!=1)
{
if(b%tem)return -1;
++d;
c/=tem;
b/=tem;
D=D*a/tem%c;
}
int m=(int)ceil(sqrt((double)c));
for(buf=1%c,i=0;i<=m;buf=buf*a%c,++i)ins(i,buf);
for(i=0,k=pow((long long)a,m,c);i<=m;D=D*k%c,++i)
{
tem=inval((int)D,b,c);
int w;
if(tem>=0&&(w=find(tem))!=-1)
return i*m+w+d;
}
return -1;
}
int main()
{
int a,b,c;
while(scanf("%d%d%d",&a,&c,&b)!=EOF)
{
if(b>=c){puts("Orz,I can’t find D!");continue;}//注意這個地方,有點變動,需要在這裏改正下,否則你就會WA
b%=c;
int tem=Baby(a,b,c);
if(tem<0)puts("Orz,I can’t find D!");
else printf("%d\n",tem);
}
return 0;
}
這個我前邊也寫過相似的一道題,你們可以去我那裏看一下解高次同餘方程