小技巧函数

字符数组快速求最小字典

 原理不多说,用笔在纸上模拟一下就会懂的。

 1 int Min_index(char *ss){
 2     int i = 0,j = 1, k = 0;
 3     int len = strlen(ss);
 4     while(i<len && j<len && k<len){
 5         int t = ss[(j+k)%len]-ss[(i+k)%len];
 6         if(t == 0)k++;
 7         else{
 8             if(t>0) j+=k+1;
 9             else i+=k+1;
10             k=0;
11         }
12         if(i==j)j++;
13     }
14     return min(i,j);
15 }

同理,也可以快速求最大字典

 

 

 

求质因子,在欧拉函数和莫比乌斯函数用的上。

 1 int fun(int x){
 2     int res = 0;
 3     for(int i = 2; i <= sqrt(x); i ++){
 4         if(x%i==0){
 5             res++;
 6             while(x%i==0)x/=i;
 7         }
 8     }
 9     if(x > 1) res++;
10     return res;
11 }

 

乘法逆元。a/b%n == a*k%n == a*inv(b,n);

 1 void exgcd(ll a, ll b, ll &x, ll &y) {
 2     if(!b){
 3         x = 1; y = 0;
 4     }else{
 5         exgcd(b, a%b, y, x);
 6         y -= x*(a/b);
 7     }
 8 }
 9 ll inv(ll a, ll n) {
10     ll x, y;
11     exgcd(a, n, x, y);
12     return (x+n)%n;
13 }

a*x+b*y=d

void exgcd(ll a, ll b,ll &d, ll &x, ll &y) {
    if(!b){
        d = a;
        x = 1; y = 0;
    }else{
        exgcd(b, a%b, d, y, x);
        y -= x*(a/b);
    }
}

 

 

上面的乘法有误差6*inv(2,mod)不等于3   费马小定理没有

费马小定理求逆元a/b%mod = a*pow_mod(b,mod-2)%mod

1 ll pow_mod(ll x, ll n){  
2     ll res=1;  
3     while(n>0){  
4         if(n&1)res=res*x%mod;  
5         x=x*x%mod;  
6         n>>=1;  
7     }  
8     return res;  
9 }

 

 基姆拉尔森公式,计算某日是星期几

1 int day(int y, int m, int d) {
2     if(m == 1 || m == 2) {
3         m += 12;
4         y --;
5     }
6     int w = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7;
7     return w;
8 }

 

求C(n,m)%p,都是在[1,1e18]范围内

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N = 15;
 5 ll qmul(ll a,ll p,ll m){
 6     ll tmp = 0;
 7     while(p){
 8         if(1&p) tmp = (tmp+a)%m;
 9         a = (a+a)%m;
10         p>>=1;
11     }
12     return tmp;
13 }
14 void exgcd(ll a,ll b,ll &x,ll &y,ll &d){
15     if(!b) d=a,x = 1,y=0;
16     else exgcd(b,a%b,y,x,d),y-=(a/b)*x;
17 }
18 ll inv(ll a,ll p){
19     ll x,y,d;
20     exgcd(a,p,x,y,d);
21     return d==1?(x+p)%p:-1;
22 }
23 ll fat(ll x,ll p){
24     ll ans = 1;
25     for( int i = 2 ; i <= x ; i ++ ) ans = ( ans * i ) % p;
26     return ans;
27 }
28 ll c(ll n,ll m,ll p){
29     if (m < 0 || m > n) return 0; 
30     return fat(n,p)*inv(fat(m,p),p)%p*inv(fat(n-m,p),p)%p;
31 }
32 ll crt(ll *a,ll *m,int n){
33     ll M = 1,res = 0;
34     for( int i = 0 ; i < n ; i++ ) M*=m[i];
35     for( int i = 0 ; i < n ; i++ ){
36         ll w = M/m[i];
37         res = (res+qmul(w*inv(w,m[i]),a[i],M))%M;
38     }
39     return (res+M)%M;
40 }
41 ll Lucas(ll n,ll m,ll p){
42     return m?Lucas(n/p,m/p,p)*c(n%p,m%p,p)%p:1;
43 }
44 int main() {
45     ll a[N], p[N];
46     ll t, n, m, k;
47     cin >> t;
48     while(t--) {
49         cin >> n >> m >> k;
50         for(int i = 0; i < k; i ++) {
51             cin >> p[i];
52             a[i] = Lucas(n, m, p[i]);
53         }
54         printf("%lld\n",crt(a, p, k));
55     }
56     return 0;
57 }
Lucas

 

posted @ 2017-07-10 11:01  starry_sky  阅读(292)  评论(0编辑  收藏  举报