首页 > 代码库 > hdu 5651 重复全排列+逆元
hdu 5651 重复全排列+逆元
知识点:
n个元素,其中a1,a2,····,an互不相同,进行全排列,可得n!个不同的排列。
若其中某一元素ai重复了ni次,全排列出来必有重复元素,其中真正不同的排列数应为 ,即其重复度为ni!
同理a1重复了n1次,a2重复了n2次,····,ak重复了nk次,n1+n2+····+nk=n。
对于这样的n个元素进行全排列,可得不同排列的个数实际上是
由于题目要求是对100000007取余 同余定理中对于同一个除数,两个数的乘积与它们余数的乘积同余。但这里有除法所以得用上逆元
逆元
-
定义:
满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元。eg: 1=5*3-14 所以5关于模14的乘法逆元为3. -
应用:
当我们要求 (a/b) mod P 的值时,如果 a 很大,无法直接求得a/b的值时,我们就可以使用乘法逆元。我们可以通过求b关于P的乘法逆元k,将a乘上k再模P,即(a%P*k)。其结果与(a/b) mod P等价。
关于逆元的求解方法日后在做总结 这里用的是exgcd
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long LL; const LL MOD=1e9+7; int cnt[260]; char ch[1005]; LL jiecheng(int n) { if(n==0) return 1; LL ans=1; for(int i=1;i<=n;i++) ans=ans*i%MOD; return ans; } LL x,y; LL gcd(LL a,LL b) { LL t,d; if(b==0) { x=1,y=0; return a; } d=gcd(b,a%b); t=x, x=y, y=t-(a/b)*y; return d; } int main() { int t; cin>>t; while(t--) { memset(cnt,0,sizeof(cnt)); scanf("%s",ch); int len=strlen(ch); for(int i=0;i<len;i++) { cnt[ch[i]-‘ ‘]++; } int count=0; for(int i=0;i<260;i++) { if(cnt[i]&1) count++; cnt[i]/=2; } if(count>1) { cout<<0<<endl; continue; } LL ans=jiecheng(len/2)%MOD; for(int i=0;i<260;i++) { if(cnt[i]>0) { gcd(jiecheng(cnt[i]),MOD); if(x<0) x+=MOD;// 求逆元 ans=ans*x%MOD; } } cout<<ans<<endl; } }
hdu 5651 重复全排列+逆元
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。