zoukankan      html  css  js  c++  java
  • 数论-FTT 和 NTT

    FTT

    NKOJ3071 高精度乘(输入 a, b ,输出两个数的积)

     1 #include <stdio.h>
     2 #include <complex>
     3 #include <math.h>
     4 
     5 using namespace std;
     6 
     7 typedef complex<double> CP;
     8 typedef long long LL;
     9 
    10 const int _N = 300005;
    11 const double PI = asin(1)*2;
    12 
    13 LL rev[_N], Ans[_N];
    14 char str1[_N], str2[_N];
    15 CP X[_N], Y[_N];
    16 
    17 void GetRev(LL bit)
    18 {
    19     for (LL i = 0; i < (1<<bit); ++i)
    20         rev[i] = (rev[i>>1]>>1) | ((i&1)<<(bit-1));
    21     return;
    22 }
    23 
    24 void FFT(CP *A, LL n, LL ty)
    25 {
    26     LL i, k, len;
    27     for (i = 0; i < n; ++i)
    28         if (i < rev[i]) swap(A[i], A[rev[i]]);
    29         
    30     for (len = 1; len < n; len <<= 1) {
    31         CP wn = exp(CP(0, ty*PI/len));
    32         for (i = 0; i < n; i += len<<1) {
    33             CP wi(1, 0);
    34             for (k = i; k < i+len; ++k) {
    35                 CP t0 = A[k], t1 = wi*A[k+len];
    36                 A[k] = t0+t1, A[k+len] = t0-t1;
    37                 wi *= wn;
    38             }
    39         }
    40     }
    41     if (ty == -1)
    42         for (i = 0; i < n; ++i) A[i] /= n;
    43     return;
    44 }
    45 
    46 bool Input(LL &len, char *str)
    47 {
    48     char tt; bool flag = false; int i;
    49     while (((tt = getchar()) < '0' || tt > '9') && tt != '-');
    50     if (tt == '-') flag = true, i = -1;
    51     else str[0] = tt, i = 0;
    52     while ((tt = getchar()) >= '0' && tt <= '9') str[++i] = tt;
    53     len = i+1;
    54     return flag;
    55 }
    56 
    57 int main()
    58 {
    59     LL flag1, flag2, l1, l2, i;
    60     flag1 = Input(l1, str1), flag2 = Input(l2, str2);
    61 //    printf("
    
    %s %s
    
     %lld %lld
    ", str1, str2, l1, l2);
    62     LL a = 1, x = 0;
    63     while (a < l1+l2-1) a <<= 1, ++x;
    64 //    printf("
    
    a = %lld, x = %lld
    
    ", a, x);
    65     for (i = 0; i < l1; ++i) X[i] = (double)(str1[l1-1-i]-'0');
    66     for (i = 0; i < l2; ++i) Y[i] = (double)(str2[l2-1-i]-'0');
    67     GetRev(x), FFT(X, a, 1), FFT(Y, a, 1);
    68     for (i = 0; i < a; ++i) X[i] *= Y[i];
    69     FFT(X, a, -1);
    70     for (i = 0; i < l1+l2; ++i)
    71         Ans[i] += (long long)(X[i].real() + 0.5), Ans[i+1] += Ans[i]/10, Ans[i] %= 10;
    72     for (i = l1+l2; i >= 0 && !Ans[i]; --i);
    73     if (i == -1) { printf("0
    "); return 0; }
    74     if (flag1 ^ flag2) putchar('-');
    75     while (i >= 0) putchar(Ans[i] + '0'), --i;
    76     putchar('
    ');
    77     return 0;
    78 }

    NTT

    1.数论阶和原根

    相关文章:数论之原根 https://blog.csdn.net/fuyukai/article/details/50894609

    orda 表示当 a, n 互素时,在模 n 意义下,a 的数论阶,即满足 ax Ξ 1 (mod n) 的最小正整数 x .

    结论:(orda) | x

    推论:(orda) | phi(x)

    当 n > 0 且 orda = phi(n) 时,a 为 n 的一个原根.

    素数一定有原根,整数不一定. 当一个数 n 有原根时,它的原根数量是 phi(phi(n)) .

    在模 n 意义下,n 的原根为 g,gi 互不相同 , 0 <= i <= phi(n) - 1

    这一点性质类似 FFT 中的单位根 w ,也就是 NTT 的基础。

    求素数 n 的原根

    从小到大枚举每一个 x | phi(n) , 判断是否满足 ax Ξ 1 (mod n),找到一个合理的 x 即为 n 的原根.

    2.NTT操作

     1 #include <stdio.h>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 typedef long long LL;
     7 
     8 const int _N = 300005;
     9 const long long P = 998244353LL;
    10 const long long G = 3LL;
    11 
    12 LL rev[_N], Ans[_N];
    13 char str1[_N], str2[_N];
    14 LL X[_N], Y[_N];
    15 
    16 void GetRev(LL bit)
    17 {
    18     for (LL i = 0; i < (1<<bit); ++i)
    19         rev[i] = (rev[i>>1]>>1) | ((i&1)<<(bit-1));
    20     return;
    21 }
    22 
    23 LL Mont(LL t1, LL t2)
    24 {
    25     t1 %= P;
    26     LL ans = 1;
    27     while (t2) {
    28         if (t2 & 1) ans = ans*t1%P;
    29         t2 >>= 1, t1 = t1*t1%P;
    30     }
    31     return ans;
    32 }
    33 
    34 void NTT(LL *A, LL n, LL ty)
    35 {
    36     LL i, k, len;
    37     for (i = 0; i < n; ++i)
    38         if (i < rev[i]) swap(A[i], A[rev[i]]);
    39         
    40     for (len = 1; len < n; len <<= 1) {
    41         LL wn = Mont(G, (P-1)+ty*(P-1)/(len<<1));
    42         for (i = 0; i < n; i += len<<1) {
    43             LL wi = 1;
    44             for (k = i; k < i+len; ++k) {
    45                 LL t0 = A[k], t1 = wi*A[k+len]%P;
    46                 A[k] = t0+t1, A[k+len] = t0-t1;
    47                 if ((A[k] = t0+t1) >= P) A[k] -= P;
    48                 if ((A[k+len] = t0-t1) < 0) A[k+len] += P;
    49                 wi = wi*wn%P;
    50             }
    51         }
    52     }
    53     if (ty == -1) {
    54         LL tmp = Mont(n, P-2);
    55         for (i = 0; i < n; ++i) A[i] = A[i]*tmp%P;
    56     }
    57     return;
    58 }
    59 
    60 bool Input(LL &len, char *str)
    61 {
    62     char tt; bool flag = false; int i;
    63     while (((tt = getchar()) < '0' || tt > '9') && tt != '-');
    64     if (tt == '-') flag = true, i = -1;
    65     else str[0] = tt, i = 0;
    66     while ((tt = getchar()) >= '0' && tt <= '9') str[++i] = tt;
    67     len = i+1;
    68     return flag;
    69 }
    70 
    71 int main()
    72 {
    73     LL flag1, flag2, l1, l2, i;
    74     flag1 = Input(l1, str1), flag2 = Input(l2, str2);
    75 //    printf("
    
    %s %s
    
     %lld %lld
    ", str1, str2, l1, l2);
    76     LL a = 1, x = 0;
    77     while (a < l1+l2-1) a <<= 1, ++x;
    78 //    printf("
    
    a = %lld, x = %lld
    
    ", a, x);
    79     for (i = 0; i < l1; ++i) X[i] = str1[l1-1-i]-'0';
    80     for (i = 0; i < l2; ++i) Y[i] = str2[l2-1-i]-'0';
    81     GetRev(x), NTT(X, a, 1), NTT(Y, a, 1);
    82     for (i = 0; i < a; ++i) X[i] = X[i]*Y[i]%P;
    83     NTT(X, a, -1);
    84     for (i = 0; i < l1+l2; ++i)
    85         Ans[i] += X[i], Ans[i+1] += Ans[i]/10, Ans[i] %= 10;
    86     for (i = l1+l2; i >= 0 && !Ans[i]; --i);
    87     if (i == -1) { printf("0
    "); return 0; }
    88     if (flag1 ^ flag2) putchar('-');
    89     while (i >= 0) putchar(Ans[i] + '0'), --i;
    90     putchar('
    ');
    91     return 0;
    92 }
  • 相关阅读:
    mysql数据类型
    Hive Getting Started补充
    Hive安装
    HDFS High Availability Using the Quorum Journal Manager
    用DBContext (EF) 实现通用增删改查的REST方法
    Internet Explorer 10 administration IE10管理
    配置AD RMS及SharePoint 2013 IRM问题解决及相关资源
    SharePoint 2013 首页修改
    Status: Checked in and viewable by authorized users 出现在sharepoint 2013 home 页面
    添加AD RMS role时,提示密码不能被验证The password could not be validated
  • 原文地址:https://www.cnblogs.com/ghcred/p/8981471.html
Copyright © 2011-2022 走看看