hdu 2815 Mod tree 高次同余方程

Hdu 2815

题目大意就是说:有棵树,每个节点有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;
}

这个我前边也写过相似的一道题,你们可以去我那里看一下解高次同余方程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值