码迷,mamicode.com
首页 > 其他好文 > 详细

HDU2815 Mod Tree【高次同余方程】

时间:2015-03-18 12:31:41      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2815


题目大意:

有一颗树,每个节点有K个儿子,那么问题来了:能否算出这棵树的最小深度D,使得这个深度

的节点数对P取模的结果为N吗?


思路:

转换一下题目含义,就变成了解K^i = N(mod P),典型的A^i = B(mod C)问题,此题B的范围

明显在[0,C-1]之间,若不在此区间,方程显然无解。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL __int64
using namespace std;
const int MAXN = 65535;

struct HASH
{
    int a;
    int b;
    int next;
}Hash[MAXN*2];

int flag[MAXN+66];
int top,idx;

void ins(int a,int b)
{
    int k = b & MAXN;
    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 & MAXN;
    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)
{
    if(b == 0)
        return a;
    return GCD(b,a%b);
}

int ExGCD(int a,int b,int &x,int &y)
{
    int temp,ret;
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    ret = ExGCD(b,a%b,x,y);
    temp = x;
    x = y;
    y = temp - a/b*y;
    return ret;
}

int Inval(int a,int b,int n)
{
    int x,y,e;
    ExGCD(a,n,x,y);
    e = (LL)x*b%n;
    return e < 0 ? e + n : e;
}

int PowMod(LL a,int b,int c)
{
    LL ret = 1%c;
    a %= c;
    while(b)
    {
        if(b&1)
            ret = ret*a%c;
        a = a*a%c;
        b >>= 1;
    }
    return ret;
}

int BabyStep(int A,int B,int C)
{
    top = MAXN;
    ++idx;
    LL buf = 1%C,D = buf,K;
    int d = 0,temp,i;
    for(i = 0; i <= 100; buf = buf*A%C,++i)
    {
        if(buf == B)
            return i;
    }

    while((temp = GCD(A,C)) != 1)
    {
        if(B % temp)
            return -1;
        ++d;
        C /= temp;
        B /= temp;
        D = D*A/temp%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 = PowMod((LL)A,M,C); i <= M; D = D*K%C,++i)
    {
        temp = Inval((int)D,B,C);
        int w;
        if(temp >= 0 && (w = Find(temp)) != -1)
            return i * M + w + d;
    }
    return -1;
}

int main()
{
    int A,B,C;
    while(~scanf("%d%d%d",&A,&C,&B))
    {
        if(B > C)
        {
            printf("Orz,I can’t find D!\n");
            continue;
        }
        B %= C;
        int temp = BabyStep(A,B,C);
        if(temp < 0)
            printf("Orz,I can’t find D!\n");
        else
            printf("%d\n",temp);
    }

    return 0;
}


HDU2815 Mod Tree【高次同余方程】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/44407087

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!