vjudge上题目链接:Huge Mods
附上截图:
题意不难理解,因为指数的范围太大,所以我就想是不是需要用求幂大法: AB % C = AB % phi(C) + phi(C) % C ( B > phi(C) ) 呢?后来发现确实需要用到,而且因为它有很多重指数,所以需要 dfs,深搜到最后一层后才返回,每次向上一层返回用求幂公式处理好的指数,然后本层用同样的原理去处理好当前层取模的值,并向上一层返回。欧拉函数预处理即可,这题的结束也有点卡人,我是用输入挂来处理的。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int M = 10006; 6 7 int phi[M] = {0,1,}; 8 inline void init(int n = M - 3) { 9 for(int i = 2; i <= n; ++i) 10 if(!phi[i]) 11 for(int j = i; j <= n; j += i) { 12 if(!phi[j]) phi[j] = j; 13 phi[j] = phi[j] / i *(i - 1); 14 } 15 } 16 17 #include<cctype> 18 inline int read(int &x) { 19 x = 0; 20 char ch = getchar(); 21 while(!isdigit(ch) && ch != ‘#‘) ch = getchar(); 22 if(ch == ‘#‘) return 0; 23 while(isdigit(ch)) { 24 x = x * 10 + (ch - ‘0‘); 25 ch = getchar(); 26 } 27 return 1; 28 } 29 30 int quick_mod(int a, int b, int m) { 31 int res = 1; 32 while(b) { 33 if(b & 1) res = res * a % m; 34 a = a * a % m; 35 b >>= 1; 36 } 37 return res; 38 } 39 40 int m,n,a[16]; 41 42 // id 为当前层的数组下标,mod 为当前层进行取模的模数, 43 // 由求幂公式可知 mod 每次向下一层传参时是传当前层的 mod 的欧拉函数,也就是 phi[mod] 的值 44 // dfs 向上一层返回用求幂公式处理好的指数,更多的参看代码了 45 int dfs(int id, int mod) { 46 if(id == n) { 47 if(a[id] > mod) return a[id] % mod + mod; 48 else return a[id]; 49 } 50 int pow = dfs(id + 1, phi[mod]); 51 52 int mul = 1, c = a[id], num = pow; 53 54 // 因为忽略了 c <= mod 这个判断导致中间数据溢出,害我 TLE 了数次,T 得不明真相, 55 // 还在想是不是复杂度算错了,害得我一步步来痛苦地去调试 T.T 56 while(num && mul <= mod && c <= mod) { 57 if(num & 1) mul *= c; 58 c *= c; 59 num >>= 1; 60 } 61 if(num && (mul > mod || c > mod)) return quick_mod(a[id], pow, mod) + mod; 62 else return mul; 63 } 64 65 int main() { 66 int Case = 0; 67 init(); 68 while(read(m)) { 69 read(n); 70 for(int i = 1; i <= n; ++i) 71 read(a[i]); 72 printf("Case #%d: %d\n",++Case, dfs(1,m) % m); 73 } 74 return 0; 75 }
好久没做数论题了,果然很爽的感觉!虽然很难,虽然我还有 n 多的 XX 定理不会,不过我不会放弃这个如此吸引人的数学分支的,想当初搞 ACM 有很大原因也是因为她~
时间: 2024-11-05 18:42:25