uva 10692 Huge Mods 超大数取模

  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 }
View Code

  好久没做数论题了,果然很爽的感觉!虽然很难,虽然我还有 n 多的 XX 定理不会,不过我不会放弃这个如此吸引人的数学分支的,想当初搞 ACM 有很大原因也是因为她~

转载于:https://www.cnblogs.com/Newdawn/p/4693976.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值