组合数相关问题
http://blog.csdn.net/acdreamers/article/details/8037918
上面的是lucas的讲解 感觉好清晰
除以 阶乘就等于乘以逆元 当然 mod是素数
lucas 就有如此应用
上个例题吧
HDOJ——5651
这个题 果组合数死 可以用杨辉三角和lucas过
ll com(ll n,ll m) //计算组合数C(n,m) { ll sum=1; //线性计算 for(ll i=1,j=n;i<=m;i++,j--) sum=(sum*j)/i; return sum; }
杨辉三角AC代码
#include<cstdio> #include<map> #include<vector> #include<stack> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<cstdlib> #include<climits> #define PI acos(-1.0) #define INF 0x3fffffff using namespace std; typedef __int64 ll; typedef __int64 int64; const ll MOD=1e9+7; const int64 Mod=1e9+7; const double eps=1e-9; const int N=32768; const int MAXN=200000; typedef int rl; inline void r(rl&num){ num=0;rl f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar(); num*=f; } int c[1010][1010]; char ch[1010]; int a[27]; int main(){ for(int i=0;i<1010;i++) { c[i][i]=c[i][0]=1; } for(int i=0;i<1010;i++) { for(int j=1;j<=i;j++) { c[i][j]=(c[i-1][j-1]+c[i-1][j])%Mod; } } int T; r(T); while(T--){ scanf("%s",ch); int len=strlen(ch); for(int i=0;i<len;i++) { a[ch[i]-'a']++; } int sum=0,s=0; for(int i=0;i<26;i++) { if(a[i]&1){ a[i]--; sum++; } if(a[i]){ s++; } } if(sum>1){ printf("0\n"); } else{ if(s==0||s==1){ printf("1\n"); } else{ len=(len-sum)/2; int64 x=1; for(int i=0;i<26&&s>1;i++) { if(a[i]){ s--; x*=c[len][a[i]/2]; len-=a[i]/2; x%=Mod; } } printf("%I64d\n",x); } } memset(a,0,sizeof(a)); } return 0; }
改动一点 但是死了
#include<cstdio> #include<map> #include<vector> #include<stack> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<cstdlib> #include<climits> #define PI acos(-1.0) #define INF 0x3fffffff using namespace std; typedef __int64 ll; typedef __int64 int64; const ll MOD=1e9+7; const int64 Mod=1e9+7; const double eps=1e-9; const int N=1e3+10; const int MAXN=200000; typedef int rl; inline void r(rl&num){ num=0;rl f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar(); num*=f; } ll f[N]; void init(int p) { //f[n] = n! f[0] = 1; for (int i=1; i<=p; ++i) f[i] = f[i-1] * i % p; } ll pow_mod(ll a, ll x, int p) { ll ret = 1; while (x) { if (x & 1) ret = ret * a % p; a = a * a % p; x >>= 1; } return ret; } ll Lucas(ll n, ll k, int p) { //C (n, k) % p ll ret = 1; while (n && k) { ll nn = n % p, kk = k % p; if (nn < kk) return 0; //inv (f[kk]) = f[kk] ^ (p - 2) % p ret = ret * f[nn] * pow_mod (f[kk] * f[nn-kk] % p, p - 2, p) % p; n /= p, k /= p; } return ret; } char ch[1010]; int a[27]; int main(){ int T; init(N-1); r(T); while(T--){ scanf("%s",ch); int len=strlen(ch); for(int i=0;i<len;i++) { a[ch[i]-'a']++; } int sum=0,s=0; for(int i=0;i<26;i++) { if(a[i]&1){ a[i]--; sum++; } if(a[i]){ s++; } } if(sum>1){ printf("0\n"); } else{ if(s==0||s==1){ printf("1\n"); } else{ len=(len-sum)/2; int64 x=1; for(int i=0;i<26&&s>1;i++) { if(a[i]){ s--; x*=Lucas(len,a[i]/2,Mod); len-=a[i]/2; x%=Mod; } } printf("%I64d\n",x); } } memset(a,0,sizeof(a)); } return 0; }
问了利文学长后 改为
#include<cstdio> #include<map> #include<vector> #include<stack> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<cstdlib> #include<climits> #define PI acos(-1.0) #define INF 0x3fffffff using namespace std; typedef __int64 ll; typedef __int64 LL; typedef __int64 int64; const ll MOD=1e9+7; const int64 Mod=1e9+7; const ll p=1e9+7; const double eps=1e-9; const int N=1e3+10; const int MAXN=200000; typedef int rl; inline void r(rl&num){ num=0;rl f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar(); num*=f; } LL quick_mod(LL a, LL b) { LL ans = 1; a %= p; while(b) { if(b & 1) { ans = ans * a % p; b--; } b >>= 1; a = a * a % p; } return ans; } LL C(LL n, LL m) { if(m > n) return 0; LL ans = 1; for(int i=1; i<=m; i++) { LL a = (n + i - m) % p; LL b = i % p; ans = ans * (a * quick_mod(b, p-2) % p) % p; } return ans; } LL Lucas(LL n, LL m) { if(m == 0) return 1; return C(n % p, m % p) * Lucas(n / p, m / p) % p; } char ch[1010]; int a[27]; int main(){ int T; r(T); while(T--){ scanf("%s",ch); int len=strlen(ch); for(int i=0;i<len;i++) { a[ch[i]-'a']++; } int sum=0,s=0; for(int i=0;i<26;i++) { if(a[i]&1){ a[i]--; sum++; } if(a[i]){ s++; } } if(sum>1){ printf("0\n"); } else{ if(s==0||s==1){ printf("1\n"); } else{ len=(len-sum)/2; int64 x=1; for(int i=0;i<26&&s>1;i++) { if(a[i]){ s--; x*=Lucas(len,a[i]/2); len-=a[i]/2; x%=Mod; } } printf("%I64d\n",x); } } memset(a,0,sizeof(a)); } return 0; }
换个思路问题 可以用 N!/a[0]!/..../a[25]! 乘逆元计算