HDU - 3307 Description has only two Sentences

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 a 0 = 0.
Input
Each line will contain only three integers X, Y, a 0 ( 1 < X < 2 31, 0 <= Y < 2 63, 0 < a 0 < 2 31).
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

题意:
a n = X*a n-1 + Y and Y mod (X-1) = 0
给出X,Y,a0,计算最小正整数k,即ak mod a0 =0。

思路:
式子化简后得到a n=X ^ na0 + ((x^n -1)/(1-x))Y
因为Y mod (X-1) = 0
所以可假设Y =c * (X-1)
带入上式得到:
a n=X ^ n
a0 + ((x^n -1)/(1-x))
(c * (X-1) )
a n=X ^ n*a0 + (x^n -1) * c
由此可以看出要想使an%a0==0则 (x^n -1) * c%a0 ==0
所以可以先去掉c因子中a0的因子(a0/gcd(a0,c)),然后可以写成x^n=1(mod a0),所以当n等于a0的欧拉函数值的时候式子一定成立(x与a0互质)(欧拉定理),然后就遍历1<=n<<φ(a0)求最小的n。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define ll long long
ll gcd(ll a,ll b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
ll pan(ll a,ll n,ll m)
{
    ll ans=1;
    while(n)
    {
        if(n%2)
        ans*=a;
        n/=2;
        a*=a;
        a%=m;
        ans%=m;
    }
    return ans%m;
}
int phi(int x)
{
    int ans = x;
    for(int i = 2; i*i <= x; i++)
    {
        if(x % i == 0)
        {
            ans = ans / i * (i-1);
            while(x % i == 0) x /= i;
        }
    }
    if(x > 1) ans = ans / x * (x-1);
    return ans;
}
int main()
{
    ll x,y,a;
    while(scanf("%lld%lld%lld",&x,&y,&a)!=EOF)
    {
        ll c=y/(x-1);
        ll d=gcd(c,a);
        a/=d;
        if(gcd(x,a)!=1)
    {
        printf("Impossible!\n");
        continue;
    }
    ll s=phi(a);
    ll k=s;
    for(ll i=2;i*i<=s;i++)
    {
        if(s%i==0)
        {
            if(pan(x,i,a)==1)
            k=min(k,i);
        if(pan(x,s/i,a)==1)
            k=min(k,s/i);
        }
    }
    printf("%lld\n",k);
    }

}
发布了241 篇原创文章 · 获赞 14 · 访问量 5247
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览