/**//* 给出n个1,m个0,组成一个串,要求这个串的任意前缀都有1的个数>=0的个数 求满足这样的串的个数 n,m <= 10^6
脑残丫,很明显的“进栈出栈”,居然没反应 计数公式为 (n+m, m) - (n+m, m-1)
(n+m)!(n-m+1) = ------------------ (n+1)!m!
O(n)的计算会超时,要对N!分解质因子 用到公式N!里质因子p的个数为 N/p + N/p^2 +
这要注意别忘记对(n-m+1)分解质因子了,如果放在最后来乘它的话,有可能对某个质因子p,只用那三个算到的 幂小于0,而20100501又不是素数,就难算 p^x % 20100501 , x < 0 因为欧拉定理 a^x % n = a ^(x % phi(n) ) % n 需要 (a,n) = 1!!!! 八中 1856跟这题一样,不过那里的20100403是素数,可以那样搞 p^x
参考 http://hi.baidu.com/matrush/blog/item/5298d8a3786b478546106447.html */ #include<iostream> #include<cstring> #include<map> #include<algorithm> #include<stack> #include<queue> #include<cmath> #include<string> #include<cstdlib> #include<vector> #include<cstdio> #include<set> #include<list> #include<numeric> #include<cassert> #include<ctime>
using namespace std;
const int MOD = 20100501; const int MAXN = 2000000;
bool isPrime[MAXN+10]; int pr[MAXN] , tot;
void init(){ for(__int64 p = 2 ; p < MAXN ; p ++){ if(!isPrime[p]){ pr[tot++] = p; for(__int64 j = p * p ; j < MAXN ; j += p){ isPrime[j] = true; } } } }
/**//* 1*2**n tot = n/p , n/p^2 , */ int get(int p, int n){ int tot = 0; while(n > 0){ tot += n / p; n /= p; } return tot; }
int ipow(int a , int n){ if ( n == 0 ) { return 1; } if (n ==1 ) { return a % MOD; } __int64 ans = ipow(a, n/2); ans = ans * ans % MOD; if ( n&1 ) { ans = ans * a % MOD; } return ans; }
int solve(int n, int m){ if(n < m){ return 0; } /**//* (n+m)!(n-m+1) ------------------ m!(n+1)! */ __int64 ans = 1; int nm = n - m + 1; for(int i = 0 ; i < tot && pr[i] <= (n+m) ; i++){ int cnt = 0; while(nm % pr[i] == 0){ nm /= pr[i]; cnt++; } ans = ans * ipow(pr[i], get(pr[i], n+m) - get(pr[i], m) - get(pr[i], n+1) + cnt) % MOD; } return ans; }
int main() { #ifndef ONLINE_JUDGE //freopen("in","r",stdin); #endif init(); int T; for (scanf("%d",&T); T-- ; ) { int n, m; scanf("%d%d", &n, &m); printf("%d\n", solve(n,m)); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|