题目链接
Description has only two Sentences
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1963 Accepted Submission(s): 585
Problem Description
an = X*an-1 + Y and Y mod (X-1) = 0.
Your task is to calculate the smallest positive integer k that ak 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
Author
WhereIsHeroFrom
Source
HDOJ Monthly Contest – 2010.02.06
思考:大致过程如下图,不过还存在着细节理解得不是很透彻,留坑以后继续思考。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
vector<pair<int,int>>p;
ll quick(ll a,ll b,ll mod){
ll ans=1;
a=a%mod;
while(b!=0){
if(b&1) ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans;
}
ll get_euler(ll n){ //欧拉函数
ll res=n,a=n;
for (ll i = 2; i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a=a/i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
void check(ll x)//分解质因数
{
for(ll i=2;i*i<=x;++i)
{
if(x%i==0)
{
int cnt=0;
while(x%i==0) cnt++,x/=i;
p.push_back({i,cnt});
}
}
if(x>1) p.push_back({x,1});
}
int main()
{
ll x,y,a0;
while(scanf("%lld %lld %lld",&x,&y,&a0)!=EOF)
{
p.clear();
y/=x-1;
a0/=__gcd(y,a0);
if(__gcd(a0,x)!=1) {//若不满足欧拉定理
printf("Impossible!\n");continue;
}
ll ans=get_euler(a0);
check(ans);
for(int i=0;i<p.size();++i)
{
for(int j=0;j<p[i].second;++j)
if(quick(x,ans/p[i].first,a0)==1) ans/=p[i].first;
}
printf("%lld\n",ans);
}
}