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\n", 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\n" );
112         else printf( "%d\n", 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\n", tot );
193         for( int i=0; i<tot; i++ )
194             fprintf( stderr, "%d %d\n", aa[i], mm[i] );
195 */
196         printf( "%lld\n", 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 }

时间: 2024-10-19 14:08:17

bzoj 3283 扩展BSGS + 快速阶乘的相关文章

BZOJ 2242 [SDOI2011]计算器 BSGS+快速幂+EXGCD

题意:链接 方法: BSGS+快速幂+EXGCD 解析: BSGS- 题解同上.. 代码: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MOD 140345 using namespace std; typedef long long ll; ll t,k,ans; ll y,z,p;

DiscuzRedis 分页扩展 轻松快速分页 避免分页瓶颈

discuz-redis 扩展 轻松快速分页 避免分页瓶颈 设计原理: 1.起因: Discuz!X系列中,使用了SELECT * FROM pre_forum_thread WHERE fid=x AND displayorder IN ORDER BY xxx LIMIT x 这样的sql语句获取当前页的主题列表的.主题越多,翻页的数字越大,在mysql中就越容易出现慢查询,影响性能.表中只对回帖时间字段进行了索引,所以当使用发帖时间.回帖数.查看数排序查看翻页的时候,很容易出现慢查询. 由

Clever Y POJ - 3243 (扩展BSGS)

Clever Y POJ - 3243 题意:给a,c,b,求最小的x使得 ax≡b (mod c). 扩展BSGS算法~ 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #define ll long long 6 using namespace std; 7 const int mod=99991; 8 ll head[mod],nex

POJ 3243 Clever Y 扩展BSGS

http://poj.org/problem?id=3243 这道题的输入数据输入后需要将a和b都%p https://blog.csdn.net/zzkksunboy/article/details/73162229 在大约sqrt( p )的复杂度求出 ( a^x ) % p = b % p中的x 扩展bsgs增加了对p不是素数的情况的处理. 扩展bsgs在处理过a,b,p之后进行bsgs的时候x处理不到num以下的部分,这部分在处理a,b,p的时候处理过了(b=1输出num)所以不用考虑.

BSGS及扩展BSGS模板

BSGS #include <iostream>//poj2417 #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #define ll long long using namespace std; const int maxint=((1<<30)-1)*2+1; int A,B,C; struct Hashmap{ static

BSGS和扩展BSGS

BSGS: 求合法的\(x\)使得\(a ^ x \quad mod \quad p = b\) 先暴力预处理出\(a^0,a^1,a^2.....a^{\sqrt{p}}\) 然后把这些都存在map里 : \(map[a^x] = x\) 一个合法的x满足\(x = k\sqrt{p} + l\)使得\(a^x = b\),因此可以直接枚举k,于是有: \[a^x = a^{k\sqrt{p}} \cdot a^l = b\] \[a^l = \frac{b}{a^{k\sqrt{p}}} =

BZOJ 2242 SDOI2011 计算器 快速幂+扩展欧几里得+BSGS

题目大意:--简洁明了自己看 第一问快速幂 第二问扩展欧几里得 第三问BSGS 顺便一开始没看到p是质数0.0 去弄了EXBSGS的模板0.0 懒得改了 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1001001 using namespace std; typedef long long l

BZOJ 2242: [SDOI2011]计算器( 快速幂 + 扩展欧几里德 + BSGS )

没什么好说的... --------------------------------------------------------------------- #include<cstdio> #include<cmath> #include<map> using namespace std; typedef long long ll; int MOD; void gcd(int a, int b, int& d, int& x, int& y)

php扩展开发-快速上手

系统环境CentOS release 6.5 (Final) PHP版本php-5.6.27 扩展开发需要有php环境及php的源代码,我的PHP安装目录/home/zhangxiaomin/study/php5627/,源码目录/home/zhangxiaomin/study/php-5.6.27, ln -s /home/zhangxiaomin/study/php5627/bin/php /home/zhangxiaomin/bin/php5.6 做一个软连接用php5.6代替/home/