Codeforces Round #181 (Div. 2) C 组和+乘法逆元
逆元:http://www.cnblogs.com/E-star/archive/2013/04/26/3045412.html
题意:
给定三个数a,b,n, a, b, n (1 ≤ a < b ≤ 9, 1 ≤ n ≤ 106) 求由a,b组成的长度为n的数有多少种。
思路:
我们只要枚举a的个数i,然后n-i就是b的个数,i个a与n-i个b的排列有多少种? f[n]/(f[i]*f[n - i]) f[i]表示i的阶乘。
这里整体思路很明显出来了,可是这里仍然有一个关键就是如何求f[n]/(f[i]*f[n - i])%mod? 所以这里就要求逆元了。
运用求逆元的两种方法都可以,因为这里的mod为奇数,所以每个数肯定满足gcd(i,mod) = 1; 所以都存在逆元。
1:扩展欧几里得:
View Code
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 1000007 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; ll fac[N]; ll a,b; void init() { int i; fac[0] = 1; for (i = 1; i < N; ++i) { fac[i] = fac[i - 1]*i%mod; } } ll exp_gcd(ll a,ll b,ll &x,ll &y) { if (b == 0) { x = 1; y = 0; return a; } ll d = exp_gcd(b,a%b,x,y); ll tmp = x; x = y; y = tmp - (a/b)*y; return d; } bool isok(ll no) { while (no) { if (no%10 != a && no%10 != b) break; no /= 10; } if (no) return false; else return true; } int main() { int i; int n; scanf("%I64d%I64d%d",&a,&b,&n); init(); ll ans = 0; for (i = 0; i <= n; ++i) { ll tmp = i*a + (n - i)*b; if (!isok(tmp)) continue; ll tans = 0; ll x = 0 ,y = 0; ll ep = exp_gcd(fac[n - i],mod,x,y); x %= mod; if (x < 0) x += mod; tans = fac[n]*x%mod; x = 0; y = 0; ep = exp_gcd(fac[i],mod,x,y); x %= mod; if (x < 0) x += mod; ans = (ans + tans*x%mod)%mod; } cout<<ans<<endl; return 0; }
2:欧拉求:
View Code
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 1000007 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; ll fac[N]; ll tmp; ll a,b; ll ER(int m) { ll ans = m; for (int i = 2; i*i <= m; ++i) { if (m%i == 0) { ans = (ans - ans/i); while (m%i == 0) m /= i; } } if (m > 1) { ans = (ans - ans/m); } return ans; } void init() { int i; fac[0] = 1; for (i = 1; i < N; ++i) { fac[i] = fac[i - 1]*i%mod; } } ll Pow(ll a,ll b,ll n) { ll ans = 1; ll tp = a; while (b) { if (b&1) ans = ans*tp%n; tp = tp*tp%n; b >>= 1; } return ans; } bool isok(ll no) { while (no) { if (no%10 != a && no%10 != b) break; no /= 10; } if (no) return false; else return true; } int main() { int i; int n; scanf("%I64d%I64d%d",&a,&b,&n); tmp = ER(mod) - 1; // cout<<tmp<<endl; init(); ll ans = 0; for (i = 0; i <= n; ++i) { ll tp = i*a + (n - i)*b; if (!isok(tp)) continue; ll tans = fac[n]*Pow(fac[n - i],tmp,mod)%mod; // cout<<fac[n] << " "<<tans<<" <><>> " << fac[n]*Pow(fac[n - i],tmp,mod)<<endl; ans = (ans + tans*Pow(fac[i],tmp,mod)%mod)%mod; } cout<<ans<<endl; return 0; }