Description has only two Sentences HDU - 3307 欧拉定理

Description has only two Sentences HDU - 3307
题目:
a n = X*a n-1 + Y and Y mod (X-1) = 0.
Your task is to calculate the smallest positive integer k that a k mod a0 = 0.
Input
Each line will contain only three integers X, Y, a0 ( 1 < X < 231, 0 <= Y < 263, 0 < a0 < 231).
Output
For each case, output the answer in one line, if there is no such k, output "Impossible!".
Sample Input
2 0 9
Sample Output
        1

   就是求最小的k使a(k)满足ak mod a0 = 0.
   开始就是推公式 :
    an=a(0)*x^a(0)+(1+x+x^2+...+x^(n-1)*y;
    an%a(0)==0   ——》an%a(0)=(1+...+x^(n-1))*y%a(0)
                                                    =(x^n-1)/(x-1)*y%a(0);
          令    Y=y/(x-1) 
          原式= (x^n-1)*Y%mod==0;
          令    p=gcd(Y,mod)
                       mod=mod/p;Y=Y/p;
                                       (x^n-1)%mod==0;
                                                                      x^n%mod=1%mod;
          好吧确实不怎么好看。
          建议手动推一下。最后得到一个重要的式子:
     
                       (X^n)%mod=1%mod;
          首先对于gcd(x,mod)!=1时,无解。因为 :(X^n)%mod=0;
          然后就是一个欧拉定理了。


  





            就是这个了。
            
            那么怎么去找最小的k咧。
            首先算出    phi(mod)       (欧拉值)
            然后枚举每个因子。
         
          代码



#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1001000
using namespace std;

typedef long long ll;
ll d[maxn];
int Pow(ll a,ll b,ll mod)
{
    ll ans=1;
    a=a%mod;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return (ans%mod+mod)%mod;
}
ll phi(ll n)
{
    ll rea = n;
    for(ll i=2; i*i<=n; i++)
    {
        if(n % i == 0)
        {
            rea = rea - rea / i;
            while(n % i == 0) n /= i;
        }
    }
    if(n > 1)
        rea = rea - rea / n;
    return rea;
}
ll gcd(ll a,ll b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
int main()
{
    ll x,y,a;
    while(scanf("%lld%lld%lld",&x,&y,&a)!=EOF)
    {
        if(y==0)
        {
            puts("1");
            continue;
        }
        ll y1=y/(x-1);
        ll y2=gcd(y1,a);
        ll mod=a/y2;
        if(gcd(mod,x)!=1)
        {
            puts("Impossible!");
            continue;
        }
        else
        {
            ll ph=phi(mod);
            ll cnt=0;
            for(ll i=1;i*i<=ph;i++)
            {
                if(ph%i==0)
                {
                    d[cnt++]=i;
                    if(ph/i!=i)
                        d[cnt++]=ph/i;
                }
            }
            sort(d,d+cnt);
            for(ll i=0;i<cnt;i++)
            {
                if(Pow(x,d[i],mod)==1)
                {
                    cout<<d[i]<<endl;
                    break;
                }
            }
        }
    }
    return 0;
}










哈哈

                                                                                                                       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值