题目大意就是说:有棵树,每个节点有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;
}
这个我前边也写过相似的一道题,你们可以去我那里看一下解高次同余方程