CF300C Beautiful Numbers(排列組合/組合數取模)
阿新 • • 發佈:2021-10-22
連結:https://ac.nowcoder.com/acm/contest/21791/F
來源:牛客網
題目描述
給你兩個數字 a a和 b b。一個數是由 a,b a,b兩種數字構成,那麼這個數是good;這個數的每一位加起來構成新的一個數,並且新數也是一個good數,那麼稱原數為excell。
求 n n位數中有多少個數是excell,輸出 mod 109+7 mod 109+7 後的結果。 注意, n n位數不能有前導0。
輸入描述:
第一行包含三個整數 a,b,n(1≤a<b≤9,1≤n≤106) a,b,n(1≤a<b≤9,1≤n≤106)。
輸出描述:
輸出一個整數。表示答案 mod 109+7 mod 109+7 後的結果。
示例1
輸入
複製
1 3 3
輸出
複製
1
說明
滿足條件的三位數只有1個:111。
示例2
輸入
複製
2 3 10
輸出
複製
165
備註:
原題連結:https://codeforces.com/problemset/problem/300/C
注意到,當一個數是excell的時候,不管怎麼排列這個數的每一位,它都是excell的。因此可以列舉含有的a的個數x,進而也可以得到b的個數y。如果x個a和y個b組成的數是excell的話就把答案加上\(C_n^x\)即可(相當於從n個位置選x個位置放a)。計算組合數直接套組合數取模的板子即可。
#include <bits/stdc++.h> #define mod 1000000007 #define ll long long #define LL long long #define p 1000000007 using namespace std; ll n, a, b; bool judge(ll sum) { while(sum) { ll now = sum % 10; sum /= 10; if(now != a && now != b) { return 0; } } return 1; } const long long maxn = 2000005; void extend_gcd(LL a,LL b,LL &x,LL &y){ if(b==0){ x=1,y=0; return; } extend_gcd(b,a%b,y,x); y-=a/b*x; } ll inv[maxn + 10]; ll f[maxn + 10]; void init(){//階乘及其逆元打表 f[0]=1; for(int i=1;i<=maxn;i++){ f[i]=f[i-1]*i%p; } LL x,y; extend_gcd(f[maxn],p,x,y);//先求出f[N]的逆元,再迴圈求出f[1~N-1]的逆元 inv[maxn]=(x%p+p)%p; for(int i=maxn-1;i>=1;i--){ inv[i]=inv[i+1]*(i+1)%p; } } LL C(LL n,LL m){ if(n==m||m==0)return 1; return (f[n]*inv[m]%p*inv[n-m]%p)%p; } int main() { init(); cin >> a >> b >> n; ll ans = 0; for(ll i = 0; i <= n; i++) { ll num = i * a + (n - i) * b; if(judge(num)) { ans = (ans + C(n, i)) % mod; } } cout << ans; return 0; }