模取幂

2019-04-13 12:20发布

题目描述: 大家对指数运算都非常熟悉,定义f(n,k) = n ^ k (n的k次方), 例如f(2, 3) = 8, f(3,4) = 81。 我们定义f(0,0) = 1。 我们的目标是给定整数n1,k1,n2,k2,n,求f(f(n1,k1),f(n2,k2)) % n。 
(%是取余数运算)。 输入格式 多组数据,每组数据就一行包含5个整数n1,k1,n2,k2,n。
0<=n1,k1,n2,k2<=1000000000, 1 <= n <=10000000) 输出格式 每组数据一行,表示最终结果。 
挑战规则: 
输入样例   1 2 3 4 5 5 4 3 2 1 输出样例   1 0 解决思路: 首先理清解题方向 f(f(n1,k1),f(n2,k2))%n  => (n1^k1)^(n2^k2)%n => n1^(k1*n2^k2)%n 注意:(n1^k1)^(n2^k2) != n1^k1^n2^k2 下面主要考虑f(f(n1,k1),f(n2,k2)) > n的情况: 1.求出n1^m%n的所有可能值,并保存; 2.求出(k1*n2^k2)对于步骤1结果的个数的取余k; 3.返回1中的第k个值,如果k为0,取最后一个。 下面是具体实现,本人测过一些,都是可以的,由于csdn答题框老是加载不出来,所以请大家帮忙验证一下! /****************************************************/ // 模取幂运算 计算a^b mod c // 利用公式 // (a*b)mod(c) = ((a mod c )*b mod c /****************************************************/ int a_b_Mod_c(int a, int b, int c) {//前提 a b c 都是正数 int digit[32]; int i, k; long long resualt = 1; i = 0; while(b)//把b化成2进制 { digit[i++] = b%2; b >>= 1; } //计算(a^b) mod c for(k = i-1; k >= 0; k--) { resualt = (resualt * resualt) % c; if(digit[k] == 1) { resualt = (resualt * a) % c; } } return resualt; } //计算(b*n^k)%mod int fmod(int n, int k, int mod, int b) { long long res; if (mod < 2) return 0; res = a_b_Mod_c(n,k,mod); return (res*b)%mod; } //find all numbers n^m%mod can be int findAll(int n, int mod) { int tm = n%mod; int first = tm; long tmp = tm; int i = 1; while(1) { tmp *= tm; if (tmp > mod) { tmp = tmp%mod; if (tmp == first) break; } i++; } printf("all %d ", i); return i; } //check if (n^k)^(n1^k1)is big than to, if not return (n^k)^(n1^k1),else return 0 int bigOrMod(int n, int k, int n1, int k1, int to) { int i,j,t; long m; m = 1; for (i = 0; i < k; i++) { m *= n; if (m > to) return 0; } t = m; m = 1; for (i = 0; i < k1; i++) { for(j = 0;j < n1; j++) { m *= t; if (m > to) return 0; } } printf("%d->(%d,%d,%d):%ld ", n, k, n1, k1, m); return m; } int fffmod(int n, int k, int n1,int k1, int mod) { int i,tmp,all; long result = 1; if (mod < 2) return 0; if (!(n1&&k1))//if n1 or k1 is 0,n1^k1 will 1,don't need return fmod(n,k,mod,1); if (!(n&&k) || 1==n)//if n or k is 0,f(f(n,k),f(n1,k1)) will equal to 1 return 1; if ((tmp = bigOrMod(n,k,n1,k1,mod))!= 0) return tmp; else { printf("findall "); all = findAll(n, mod); printf("fmod "); tmp = fmod(n1, k1, all, k); tmp = tmp?tmp:all; printf("result "); result = a_b_Mod_c(n, tmp, mod); } return result; }