zoukankan      html  css  js  c++  java
  • 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
    ",++Case, dfs(1,m) % m);
    73     }
    74     return 0;
    75 }
    View Code

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

  • 相关阅读:
    我要好offer之 二叉树大总结
    我要好offer之 字符串相关大总结
    楼层扔鸡蛋问题[转]
    Linux System Programming 学习笔记(十一) 时间
    Linux System Programming 学习笔记(十) 信号
    Linux System Programming 学习笔记(九) 内存管理
    Linux System Programming 学习笔记(八) 文件和目录管理
    Linux System Programming 学习笔记(七) 线程
    Linux System Programming 学习笔记(六) 进程调度
    APUE 学习笔记(十一) 网络IPC:套接字
  • 原文地址:https://www.cnblogs.com/Newdawn/p/4693976.html
Copyright © 2011-2022 走看看