Description has only two Sentences
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1071 Accepted Submission(s): 323
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.
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
很好的一个题目。
思路:对于此数列我们可以得到其通项为:
an = a0*xn + (1+x+x2+..xn-1)Y = (xn-1)/(x-1)*Y+a0xn
假设ak%a0 = 0,那么我们代入得 ((xk-1)/(x-1)*Y+a0xk)%a0 =0 又因为题目中说过Y%(x-1)=0 所以设 Y=Y/(x-1)。
最终我们得到 ak%a0 = (xn-1)*Y%a0 = 0 接下来就是这个题目的难点了 ,这个地方我至今无法想通,如果有大牛的话请指教一二。
我们得到 d = gcd(Y,a0),那么这个式子就变成了 (xn-1)*(Y/d)%(a0/d) = 0 ,又因为 Y/d 与 a0/d 互质,取模不可能为0,设 a = a0/d 所以最终我们得到:
(xn-1)%a = 0 ----------> xn%a=1 这里就可以根据欧拉定理求解了。
欧拉定理:若n,a为正整数,且n,a互素,则: ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAAkCAIAAADKJHVZAAADv0lEQVRoge2ZzWHcIBCFOXDkTAFUQAmUMDVMDVRBEZRBFdQxbZDDSwhBQvbuyrGy0Tt5JSRgvvkTVu3WBaS+ewG3WrsxXEQ3hkvoxnAJ3RguoRvDJXRjuIRuDJfQjeES+hIMIvLQ9VvnY4gxPn33v9XJGESEiA4GxBhzzudO+gY6GQMRHVtZRJxz5076BnoSQ4wxpSQiKaUYo7W2lNJaM8bUWjEmpWStba3lnK21/brW+oyVf6w+4xcp55xSOmUxz2AgIqT4EAKsz8whhNaaUj9fKCI5Z+dcSqmUYq3t9XlE9aJKKd773VvM/KUdQYxRaw0/++T4g10/jEFEYGsRMcbgIjMDzOjpYxD0ka015xzgvaJaKxE55zr4UaWU4xJ1ikIIn8fQWjvIxg9jKKXA1jnn7onOOZh7NAoRwRaTz44J6kXlnHcxnEL6QxHRoxhWhfPJaBARZmbm1hrKA+5qrXsq6LbAyLE2nJUudjGIyN8pP49iiDEidW/1MQbkfWutMQZmRcg755g5pTQS9t53N+xLDCGMKWJMUKPqWqu17WKIMY7hX0oJIWita61IYs45ESmlGGOUUtvqwsxE5L3f+m+tNYTgnDPGGGO2GJi5z87MmLevZOUfH2AIIaAZqLVOG+6JaFTO+fgDrZSCGNoK297V6m27GEIIo9OJSAhBKRVCqLXCFtZaIqq14g3jkrz33WlSSkqpTgLVbrTAhIGZsQtkCzzerdQTyXYjRxhKKd0EKaXJHCuwx7Xx3Mq5i8E5N80Cc/Sf3vsxIo0xPSBKKZOlkAbwt9Z6DI7dpITQ70VxspJSardoHWHw3ve+eLu33drYfuWW3VtIBavp4Fy7Wj2yi8FaOwXchIGIps6tY2Dm6YVEhCtbQrsYxgVP6bG1NsbWH9dXO8QzmDXGOD1/bNCnJQutxq+i4WkM3ehdHcyUYdoCg1Kq+673flrJw9HQ+41SCjBc8Hz0M7WhPYJhKgZ4Gzwa1XGqIhMGREz/qbWejD6B/H19tUO8Ec0odovv4dX414UsvKvVI7Da5B9jrwLBjfpPIhpT9tQFjFkFvtgNh0YLpzj4ip5S/zg1CvJ4lDlBGnWUlIwxgI8O4S98ED0kZrbWouMc27Na6/ZjHsO6+ZRSKHUwtNZ6dHM06ESE5mqcFL2v1hql2BgzRl4Ioa8EDfEYWDHG1dHLe/737cRjqxM1tjyT3hNDSmn1dfKNOmj53hNDa211bPBdmo4bJr0thi9qqZ/W8X/D3hbDv6UbwyV0Y7iEbgyX0I3hEvoB8Bf+XaskXEoAAAAASUVORK5CYII=)
这里求出的欧拉函数不一定是最小的解,所以要到它的因子里面去找。
但是我还是想不通为什么要求出最大公约数之后再进行求解?
我在想是不是形如(xn-1)*y%a=0的式子可以都可以变成 (xn-1)%(a/gcd(y,a))=0进行求解???BUT,WHY??
#include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <stdlib.h> #include <math.h> using namespace std; typedef long long LL; LL e[100][2]; LL phi(LL x) { LL ans=x; for(LL 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; } LL gcd(LL a,LL b) { return b==0?a:gcd(b,a%b); } LL pow_mod(LL a,LL n,LL mod) { LL ans = 1; while(n) { if(n&1) ans=ans*a%mod; a=a*a%mod; n>>=1; } return ans; } void devide(LL ans,int &id) { for(LL i=2; i*i<=ans; i++) ///分解质因数 { if(ans%i==0) { e[id][0]=i; e[id][1]=0; while(ans%i==0) ans/=i,e[id][1]++; id++; } } if(ans>1) { e[id][0]=ans; e[id++][1]=1; } } int main() { LL X,Y,a0; while(~scanf("%lld%lld%lld",&X,&Y,&a0)) { Y = Y/(X-1); LL d = gcd(Y,a0); a0 = a0/d; if(gcd(X,a0)!=1) { printf("Impossible! "); } else { LL ans = phi(a0); int id = 0; devide(ans,id); for(int i=0; i<id; i++) { for(int j=0; j<e[i][1]; j++) { if(pow_mod(X,ans/e[i][0],a0)==1) ans/=e[i][0]; ///分解本身,得到 X^ans % a0 = 1的最小ans } } printf("%lld ",ans); } } return 0; }