zoukankan      html  css  js  c++  java
  • bzoj 3283 扩展BSGS + 快速阶乘

    T2  扩展BSGS

    T3 快速阶乘

    给定整数n,质数p和正整数c,求整数s和b,满足n! / pb = s mod pc

    考虑每次取出floor(n/p)个p因子,然后将问题转化为子问题。

      1 /**************************************************************
      2     Problem: 3283
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:1704 ms
      7     Memory:12380 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <cmath>
     13  
     14 typedef long long dnt;
     15 void exgcd( dnt a, dnt b, dnt &d, dnt &x, dnt &y ) {
     16     if( b==0 ) {
     17         x=1, y=0, d=a;
     18     } else {
     19         exgcd(b,a%b,d,y,x);
     20         y-=a/b*x;
     21     }
     22 }
     23 dnt inv( int a, int n ) {
     24     dnt d, x, y;
     25     exgcd(a,n,d,x,y);
     26     return d==1 ? (x%n+n)%n : -1;
     27 }
     28 dnt mpow( dnt a, dnt b, dnt c ) {
     29     dnt rt;
     30     for( rt=1; b; b>>=1,a=a*a%c )
     31         if( b&1 ) rt=rt*a%c;
     32     return rt;
     33 }
     34  
     35 namespace Task1 {
     36     void sov( dnt a, dnt b, dnt c ) {
     37         printf( "%lld
    ", mpow(a,b,c) );
     38     }
     39 };
     40 namespace Task2 {
     41     const int mod = 38281;
     42     const int len = mod<<3;
     43     struct Hash {
     44         int head[mod], val[len], rat[len], next[len], ntot;
     45         void init() { 
     46             ntot=0; 
     47             memset( head, 0, sizeof(head) );
     48         }
     49         void insert( int v, int r ) {
     50             int k = v % mod;
     51             ntot++;
     52             next[ntot] = head[k];
     53             val[ntot] = v;
     54             rat[ntot] = r;
     55             head[k] = ntot;
     56         }
     57         int query( int v ) {
     58             int k = v % mod;
     59             for( int t=head[k]; t; t=next[t] ) 
     60                 if( val[t]==v ) return rat[t];
     61             return -1;
     62         }
     63     }hash;
     64      
     65     dnt gcd( dnt a, dnt b ) {
     66         return b ? gcd(b,a%b) : a;
     67     }
     68     int bsgs( dnt s, dnt a, dnt b, dnt c ) {
     69         hash.init();
     70         int m = ceil(sqrt(c));
     71         for( int i=0; i<m; i++ ) {
     72             if( s==b ) return i;
     73             hash.insert( s, i );
     74             s = s*a % c;
     75         }
     76         dnt am = 1;
     77         for( int i=0; i<m; i++ )
     78             am = am*a % c;
     79         am = inv(am,c);
     80         b = b*am % c;
     81         for( int i=m; i<c; i+=m ) {
     82             int j = hash.query( b );
     83             if( j!=-1 ) return i+j;
     84             b = b*am % c;
     85         }
     86         return -1;
     87     }
     88     int exbsgs( dnt a, dnt b, dnt c ) {
     89         dnt s = 1;
     90         for( int i=0; i<32; i++ ) {
     91             if( s==b ) return i;
     92             s = s*a % c;
     93         }
     94         dnt cd;
     95         s = 1;
     96         int rt = 0;
     97         while( (cd=gcd(a,c))!=1 ) {
     98             rt++;
     99             s*=a/cd;
    100             if( b%cd ) return -1;
    101             b/=cd;
    102             c/=cd;
    103             s%=c;
    104         }
    105         int p = bsgs(s,a,b,c);
    106         if( p==-1 ) return -1;
    107         return rt + p;
    108     }
    109     void sov( int a, int b, int c ) {
    110         int res = exbsgs(a,b,c);
    111         if( res==-1 ) printf( "Math Error
    " );
    112         else printf( "%d
    ", res );
    113     }
    114 };
    115 namespace Task3 {
    116     struct Pair {
    117         int s, k;
    118         Pair( int s, int k ):s(s),k(k){}
    119     };
    120     dnt aa[50], mm[50];
    121     dnt pres[1001000];
    122     dnt pp[50], cc[50], ppp[50], tot;
    123  
    124     dnt china( int n, dnt *a, dnt *m ) {
    125         int M=1;
    126         for( int i=0; i<n; i++ ) 
    127             M *= m[i];
    128         int rt = 0;
    129         for( int i=0; i<n; i++ ) {
    130             dnt Mi = M/m[i];
    131             rt = (rt+Mi*inv(Mi,m[i])*a[i]) % M;
    132         }
    133         return rt;
    134     }
    135     void init( int p, int pp ) {
    136         pres[0] = 1;
    137         for( int i=1; i<=pp; i++ ) {
    138             if( i%p==0 ) {
    139                 pres[i] = pres[i-1];
    140             } else {
    141                 pres[i] = pres[i-1]*i % pp;
    142             }
    143         }
    144     }
    145     Pair split( int n, int p, int c, int pp ) {
    146         int b = n/p;
    147         if( b==0 ) {
    148             return Pair( pres[n], 0 );
    149         } else {
    150             Pair pr = split( b, p, c, pp );
    151             return Pair( (pr.s*pres[n%pp]%pp) * mpow(pres[pp],n/pp,pp) % pp, pr.k+b );
    152         }
    153     }
    154     void sov( int m, int n, int c ) {
    155         tot = 0;
    156         for( int i=2; i*i<=c; i++ ) {
    157             if( c%i==0 ) {
    158                 pp[tot] = i;
    159                 cc[tot] = 0;
    160                 ppp[tot] = 1;
    161                 while( c%i==0 ) {
    162                     cc[tot]++;
    163                     ppp[tot] *= pp[tot];
    164                     c/=i;
    165                 }
    166                 tot++;
    167             }
    168         }
    169         if( c!=1 ) {
    170             pp[tot] = c;
    171             cc[tot] = 1;
    172             ppp[tot] = c;
    173             tot++;
    174             c = 1;
    175         }
    176         for( int i=0; i<tot; i++ ) {
    177             init(pp[i],ppp[i]);
    178             Pair pn = split( n, pp[i], cc[i], ppp[i] );
    179             Pair pa = split( m, pp[i], cc[i], ppp[i] );
    180             Pair pb = split( n-m, pp[i], cc[i], ppp[i] );
    181             if( pn.k-pa.k-pb.k >= cc[i] ) {
    182                 aa[i] = 0;
    183                 mm[i] = ppp[i];
    184             } else {
    185                 aa[i] = pn.s * (inv(pa.s,ppp[i])*inv(pb.s,ppp[i])%ppp[i]) % ppp[i];
    186                 for( int j=0; j<pn.k-pa.k-pb.k; j++ )
    187                     aa[i] = (dnt) aa[i]*pp[i] % ppp[i];
    188                 mm[i] = ppp[i];
    189             }
    190         }
    191 /*
    192         fprintf( stderr, "tot=%d
    ", tot );
    193         for( int i=0; i<tot; i++ )
    194             fprintf( stderr, "%d %d
    ", aa[i], mm[i] );
    195 */
    196         printf( "%lld
    ", china(tot,aa,mm) );
    197     }
    198 };
    199  
    200 int main() {
    201     int n;
    202     scanf( "%d", &n );
    203     for( int i=1,opt,y,z,p; i<=n; i++ ) {
    204         scanf( "%d%d%d%d", &opt, &y, &z, &p );
    205         if( opt==1 )
    206             Task1::sov( y, z, p );
    207         else if( opt==2 ) 
    208             Task2::sov( y, z, p );
    209         else
    210             Task3::sov( y, z, p );
    211     }
    212 }
    View Code
  • 相关阅读:
    js实现打字机效果(完整实例)
    纯css高斯背景模糊(毛玻璃,伪元素,完整实例)
    vue首次缓存判断
    vue使用bus.js在兄弟组件传值
    叶子节点和tensor的requires_grad参数
    Mysql 8.x初次安装过程中遇到MySQL 服务无法启动的解决方法
    Apriori算法介绍(Python实现)
    springBoot单参数校验全局异常抛出
    解决vue 动态添加标签给标签添加自定义方法显示not function问题
    macbook pro、gitlab、SourceTree提交代码
  • 原文地址:https://www.cnblogs.com/idy002/p/4498554.html
Copyright © 2011-2022 走看看