逆元用于用于对除法运算取模的运算
表示
的逆元
求解逆元
方法一:拓展欧几里得求逆元(求单个数的逆元)
已知
同时取模得
可见是
的逆元
所以中的
int ex_gcd(int a, int b, int &x, int &y){
if (b == 0){
x = 1;
y = 0;
return a;
}
int tmp = ex_gcd(b, a % b, y, x);
y -= a/b*x;
return tmp;
}
int inv(int a, int mod){ //a对于mod的逆元
int x, y;
ex_gcd(a, mod, x, y);
return x;
}
方法二:费马小定理(求单个数的逆元)
可见是
的逆元
int fp(int x, int p){
if (p == 1) return 1 % mod;
int tmp = fp(x, p / 2);
if (p & 1) return tmp * tmp % * x % mod;
return tmp * tmp % mod;
}
int inv(int a, int mod){
return fp(a, mod - 2);
}
方法三:线性求逆元(求一段区间内的所有逆元)
假设 ;
再替换 t,k
inv[1] = 1;
for(int i = 2; i <= n ; i++)
inv[i] = ( m - m / i ) * inv[ m % i ] % m;
在求解组合数的时候,分子通常会出现某个数的阶乘,下面讲解阶乘逆元
方法一:正推(同时用到
)
将记为
inv[1]=inv_fac[i]=1;
for(int i=2;i<N;i++){
inv[i]=(mod-mod/i)*inv[mod%i]%mod; //求inv[i]
inv_fac[i]=inv[i]*inv_fac[i-1]%mod;
}
方法二:逆推(只用到
)
先用费马小定理或者拓展欧几里得先求出
inv_fac[N] = fp(fac[N], mod - 2ll);
for (int i = 999; i >= 1; i--){
inv_fac[i] = inv_fac[i + 1] * (i + 1) % mod;
}
例题HDU5651
xiaoxin juju needs helpTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2981 Accepted Submission(s): 993 Problem Description As we all known, xiaoxin is a brilliant coder. He knew **palindromic** strings when he was only a six grade student at elementry school.
Input This problem has multi test cases. First line contains a single integer T(T≤20) which represents the number of test cases.
Output For each test case, print an integer which is the number of watermelon candies xiaoxin's leader needs to buy after mod 1,000,000,007.
Sample Input 3 aa aabb a
Sample Output 1 2 1
Source
Recommend wange2014 |
code
/*
*逆元在乘法中的运用
*/
#include <bits/stdc++.h>
#define FOR(I,S,T) for(int I=(S);I<=(T);I++)
#define pb push_back
#define mp make_pair
#define eb emplace_back
using namespace std;
typedef long long ll;
const int maxn = 1e4+2;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
string s;
ll inv_fac[maxn];
ll fac[maxn];
ll fp(ll x, ll p){
if (p == 0) return 1 % mod;
ll t = fp(x, p / 2) % mod;
if (p & 1) return t * t % mod * x %mod;
return t * t % mod;
}
int cnt[maxn];
vector <int> tmp;
int main()
{
int T;cin >> T;
fac[0] = 1;
FOR(i,1,1000) fac[i] = fac[i - 1] * i % mod;
inv_fac[1000] = fp(fac[1000], mod - 2ll);
for (int i = 999; i >= 1; i--){
inv_fac[i] = inv_fac[i + 1] * (i + 1) % mod;
}
inv_fac[0] = inv_fac[1];
int f = 0;
while (T--){
tmp.clear();
cin >> s;
sort(s.begin(), s.end());
cnt[0]= 1;
f = 0;
for (int i = 1; i < s.size(); i++){
if (s[i] == s[i-1] ) cnt[i]= cnt[i - 1]+1;
else {
cnt[i] = 1;
if (cnt[i -1] & 1) f++;
if (cnt[i-1] & 1) tmp.eb(cnt[i-1]-1);
else tmp.eb(cnt[i-1]);
}
}
if (s.size() > 1){
if (cnt[s.size() - 1] & 1) f++,tmp.eb(cnt[s.size() - 1] -1);
else tmp.eb(cnt[s.size() - 1]);
}
if (f > 1){
puts("0");
continue;
}
ll ans = fac[s.size() / 2];
for (int i = 0; i < tmp.size(); i++){
ans = ans * inv_fac[tmp[i] / 2] % mod;
}
cout << ans << endl;
}
return 0;
}