 /**//*
給出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
搜索
最新評論

|
|