参考:https://blog.csdn.net/weixin_30616969/article/details/97875284
参考:https://www.luogu.com.cn/problem/solution/P3811
题目:https://www.luogu.com.cn/problem/P5684
证明:
乘法逆元:
定义: 满足ak≡1 (mod p)的k值就是a关于p的乘法逆元。
为什么要有乘法逆元呢?
当我们要求(a/b) mod p的值,且a很大,无法直接求得a/b的值时,我们就要用到乘法逆元。 我们可以通过求b关于p的乘法逆元k,将a乘上k再模p,
即(ak) mod p。其结果与(a/b) mod p等价。
证:(其实很简单。。。) 根据bk≡1 (mod p)有bk=px+1。 k=(px+1)/b。
把k代入(ak) mod p,得:
(a(px+1)/b) mod p =((apx)/b+a/b) mod p
=[((apx)/b) mod p +(a/b)] mod p
=[(p(ax)/b) mod p +(a/b)] mod p
// p[(a*x)/b] mod p=0
所以原式等于:(a/b) mod p
即a/b(mod p)=ab的逆元%p=ab^(p-2)%p
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MO=1000000007;
ll n,odd,ans;
char s[2100];
ll fac[2100],sum[200];
ll power(ll a,ll b){
ll res=1;
while(b){
if(b&1)res=res*a%MO;
a=a*a%MO;
b/=2;
}
return res;
}
int main(){
cin>>n;
cin>>s;
fac[1]=1;
for(int i=2;i<=n;i++){
fac[i]=fac[i-1]*i%MO;
}
for(int i=0;i<n;i++){
sum[s[i]]++;
}
for(int i='a';i<='z';i++){
if(sum[i]%2==1){
if(odd>0){
cout<<fac[n]<<endl;
return 0;
}
odd=i;
}
}
ans=1;
if(odd){
ans=ans*sum[odd]%MO;
sum[odd]--;
}
ans=ans*fac[n/2]%MO;
for(int i='a';i<='z';i++){
if(sum[i]>0){
ans=ans*fac[sum[i]]%MO;
ans=ans*power(fac[sum[i]/2],MO-2)%MO;
}
}
cout<<(MO+fac[n]-ans)%MO<<endl;
return 0;
}
求i=1-n之间的所有i!的逆元。
一般多用在组合数预处理中。
参考:https://www.luogu.com.cn/problem/solution/P3811