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;
}

這個我前邊也寫過相似的一道題,你們可以去我那裏看一下解高次同餘方程

發佈了52 篇原創文章 · 獲贊 15 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章