[CodeForces 300C Beautiful Numbers]组合计数

题意:十进制的每一位仅由a和b组成的数是“X数”,求长度为n,各数位上的数的和是X数的X数的个数

思路:由于总的位数为n,每一位只能是a或b,令a有p个,则b有(n-p)个,如果 a*p+b*(n-p) 为X数,则这种情况的答案就是C(n,p),将所有情况累加起来即可。

 

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define copy(a, b)          memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

//#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
//#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
template<typename T>
void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}
template<typename T>
void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}

const double PI = acos(-1.0);
const int INF = 1e9 + 7;
const double EPS = 1e-8;

/* -------------------------------------------------------------------------------- */

template<int mod>
struct ModInt {
    const static int MD = mod;
    int x;
    ModInt(ll x = 0): x(x % MD) {}
    int get() { return x; }

    ModInt operator + (const ModInt &that) const { int x0 = x + that.x; return ModInt(x0 < MD? x0 : x0 - MD); }
    ModInt operator - (const ModInt &that) const { int x0 = x - that.x; return ModInt(x0 < MD? x0 + MD : x0); }
    ModInt operator * (const ModInt &that) const { return ModInt((long long)x * that.x % MD); }
    ModInt operator / (const ModInt &that) const { return *this * that.inverse(); }

    ModInt operator += (const ModInt &that) { x += that.x; if (x >= MD) x -= MD; }
    ModInt operator -= (const ModInt &that) { x -= that.x; if (x < 0) x += MD; }
    ModInt operator *= (const ModInt &that) { x = (long long)x * that.x % MD; }
    ModInt operator /= (const ModInt &that) { *this = *this / that; }

    ModInt inverse() const {
        int a = x, b = MD, u = 1, v = 0;
        while(b) {
            int t = a / b;
            a -= t * b; std::swap(a, b);
            u -= t * v; std::swap(u, v);
        }
        if(u < 0) u += MD;
        return u;
    }

};
typedef ModInt<1000000007> mint;

const int maxn = 1e6 + 7;
bool yes[10 * maxn];
int a, b, n;
mint fac[maxn], facinv[maxn];

void pre_init() {
    fillchar(yes, 0);
    for (int i = 0; i < (1 << 7); i ++) {
        int buf = 0;
        for (int j = 0; j < 7; j ++) {
            if ((1 << j) & i) buf = buf * 10 + b;
            else buf = buf * 10 + a;
            yes[buf] = true;
        }
        yes[buf] = true;
    }
    fac[0] = facinv[0] = 1;
    for (int i = 1; i <= n; i ++) {
        fac[i] = fac[i - 1] * i;
        facinv[i] = facinv[i - 1] / i;
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    while (cin >> a >> b >> n) {
        pre_init();
        mint ans = 0;
        for (int i = 0; i <= n; i ++) {
            if (yes[b * n + (a - b) * i]) {
                ans += fac[n] * facinv[i] * facinv[n - i];
            }
        }
        cout << ans.get() << endl;
    }
    return 0;
}
posted @ 2015-08-13 09:13  jklongint  阅读(246)  评论(0编辑  收藏  举报