http://acm.hdu.edu.cn/showproblem.php?pid=3307 (欧拉 + 推导公式 + gcd)
2010-08-08 02:08
447 查看
]/* * 解题: 题目描述很简单的说,然后我们可以推得这样一个公式: an = x^n * a0 + y*sigma(x+x^2+....+x^(n-1) ) ---> an = x^n*a0 + y/(x-1)*(x^n-1); 因为题目 给定 y mod (x-1) = 0 ; 那么 如果an % a0 == 0 ; 那么 可以表示 ( y/(x-1)*(x^n-1) )%a0 == 0; 设 m = y/(x-1), g = gcd(a0,m),那么我们可以得到 ( x^n-1)%(a0/g) == 0;设c = a0/g; 转化为 x^n == 1(mod c ); 那么我们可以得到 当 gcd( c,x ) != 1 时 无解 当gcd( c,x ) == 1 时,我们可以得到 x^eular(c) == 1 ( mod c); 但是这不一定是最小的,所以我们要枚举x的约数,求得最小的。 */ import java.io.*; import java.util.*; import java.math.*; public class Main3307{ static final int N = 100000; static long num[] = new long ; //public static void main(String[] args){ public static void main(String[] args)throws IOException{ StreamTokenizer cin = new StreamTokenizer(new BufferedReader (new InputStreamReader(System.in))); long x, y, a; PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); //Scanner cin = new Scanner(System.in); //while(cin.hasNext()){ while(cin.nextToken() != StreamTokenizer.TT_EOF){ //x = cin.nextLong(); //y = cin.nextLong(); //a = cin.nextLong(); x = (long)cin.nval; cin.nextToken(); y = (long)cin.nval; cin.nextToken(); a = (long)cin.nval; long m = y / (x - 1); if(m == 0){ //System.out.println("1"); out.println("1"); continue; } long g = gcd(a, m); long c = a / g; if(gcd(c, x) != 1){ //System.out.println("Impossible!"); out.println("Impossible!"); continue; } long ans = Euler(c); int len = 0; for(int i = 1; i * i <= ans; i++){ if(ans % i == 0){ num[len++] = i; if(ans % i != i){ num[len++] = ans / i; } } } Arrays.sort(num, 0, len); int i; for(i = 0; i < len; i++){ if(erfen(x, num[i], c) == 1) break; } //System.out.println(num[i]); out.println(num[i]); } out.flush(); } static long gcd(long a, long b) { if(a < b) { long temp = a; a = b; b = temp; } /* if(b == 0) return a; return gcd(b, a % b); */ while(b > 0) { //a = b; long t = a % b; a = b; b = t; } return a; } static long Euler(long n){ long sum = n; long temp = n; for(long i = 2; i * i <= n; i++){ if(temp % i == 0){ sum = sum / i * ( i - 1); while(temp % i == 0) temp /= i; } } if(temp > 1) sum = sum / temp * (temp - 1); return sum; } static long erfen(long a, long b, long mod){ long temp = a % mod; long result = 1; while(b > 0){ if(b % 2 == 1){ result *= temp; result %= mod; b--; } else{ temp *= temp; temp %= mod; b >>= 1; } } return result; } }
相关文章推荐
- 又见GCD(http://acm.hdu.edu.cn/showproblem.php?pid=2504)
- http://acm.hdu.edu.cn/showproblem.php?pid=1108 java BIgInteger gcd
- http://acm.hdu.edu.cn/showproblem.php?pid=2879 又是一个公式的推倒
- Max Sum http://acm.hdu.edu.cn/showproblem.php?pid=1003
- http://acm.hdu.edu.cn/showproblem.php?pid=1905 素数判断 + 二分
- 最小路径覆盖&&http://acm.hdu.edu.cn/showproblem.php?pid=4160
- http://acm.hdu.edu.cn/showproblem.php?pid=1452 因子求和
- http://acm.hdu.edu.cn/showproblem.php?pid=2688&&树状数组求正序数
- Quoit Design&&http://acm.hdu.edu.cn/showproblem.php?pid=1007
- Least Common Multiple&&http://acm.hdu.edu.cn/showproblem.php?pid=1019
- http://acm.hdu.edu.cn/showproblem.php?pid=4614
- http://acm.hdu.edu.cn/showproblem.php?pid=4479
- http://acm.hdu.edu.cn/showproblem.php?pid=3790&&最短路径问题
- http://acm.hdu.edu.cn/showproblem.php?pid=1060
- http://acm.hdu.edu.cn/showproblem.php?pid=2844&&背包问题
- http://acm.hdu.edu.cn/showproblem.php?pid=2795&&线段树之求最小区间端点值
- http://acm.hdu.edu.cn/showproblem.php?pid=1272。。。
- http://acm.hdu.edu.cn/showproblem.php?pid=1272
- http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1004&ojid=2&cid=963&hide=0
- http://acm.hdu.edu.cn/showproblem.php?pid=1710