Codeforces Round #181 (Div. 2) C 组和+乘法逆元

逆元:http://www.cnblogs.com/E-star/archive/2013/04/26/3045412.html

题意:

给定三个数a,b,n,   abn (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;
}

 

 

posted @ 2013-04-26 18:17  E_star  阅读(434)  评论(0编辑  收藏  举报