CodeForces 300C Beautiful Numbers(乘法逆元/费马小定理+组合数公式+快速幂)

C. Beautiful Numbers

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Vitaly is a very weird man. He‘s got two favorite digits a and b.
Vitaly calls a positive integer good, if the decimal representation of this integer only contains digits a and b.
Vitaly calls a good number excellent, if the sum of its digits is a good number.

For example, let‘s say that Vitaly‘s favourite digits are 1 and 3,
then number 12 isn‘t good and numbers 13 or 311 are.
Also, number111 is excellent and number 11 isn‘t.

Now Vitaly is wondering, how many excellent numbers of length exactly n are there. As this number can be rather large, he asks you
to count the remainder after dividing it by 1000000007 (109?+?7).

A number‘s length is the number of digits in its decimal representation without leading zeroes.

Input

The first line contains three integers: abn (1?≤?a?<?b?≤?9,?1?≤?n?≤?106).

Output

Print a single integer — the answer to the problem modulo 1000000007 (109?+?7).

Sample test(s)

input

1 3 3

output

1

input

2 3 10

output

165

题目大意:

给出a和b,如果一个数每一位都是a或b,那么我们称这个数为good,在good的基础上,如果这个数的每一位之和也是good,那么这个数是excellent。求长度为n的excellent数的个数mod(1e9+7)。ps:1e9+7是一个质数。

解题思路:

由于题目中给出了n,所以我们可以枚举a的个数m,那么剩下的(n-m)位就是b。再判断a*m+b*(n-m)是不是good数,如果是,那么我们在答案中加上C(m,n)即可,枚举完毕即最终答案。

但是n最大为1e6,计算组合数时(C(m,n)=n!/(m!*(n-m)!))要计算n的阶乘,直接计算肯定会出现错误。

在这里介绍一些数学知识:

(1)费马小定理

费马小定理(Fermat Theory)是数论中的一个重要定理,其内容为: 假如p是质数,且Gcd(a,p)=1,那么 a(p-1)(mod p)≡1。即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。(我爱度娘(╯‵□′)╯︵┻━┻)。

简而言之就是如果a,p互质,同时p是质数,那么a^(p-1) mod p=1。证明略。

(2)乘法逆元

若对于a,p存在x,使得a*x mod p=1,那么我们称x为a对p的乘法逆元。证明略。

那么乘法逆元存在的意义是什么呢?

假如我们要求(a/b) mod p且无法直接求得a/b的值时,我们可以求出b对p的乘法逆元inv,那么(a/b) mod p=(a*inv) mod p。证明略。。。

bazinga!!!

证明如下:

假如inv是b对于p的乘法逆元,即b*inv=p*t+1(t为整数),移项得inv=(p*t+1)/b

(a*inv) mod p

=(a*((p*t+1)/b)) mod p

=(a*(p*t/b+1/b)) mod p

=(a/b) mod p+(a*(p*t+1)) mod p

=(a/b) mod p+(a*p*t/b) mod p

∵ (a*p*t/b) mod p=0

∴ 原式=(a/b) mod p

即(a*inv) mod p=(a/b) mod p

有了这2个概念我们就可以快速地算出组合数了。

我们可以知道x与x^p-2互为逆元(p是质数)。

/*

证明:x与x^(p-2)互为逆元(p是质数)

由费马小定理:x^(p-1) mod p=1

x*(x^(p-2)) mod p=1

得x与x^(p-2)互为乘法逆元,证毕。

*/

由上述结论可知,要计算C(i,n),即计算n!/(i!*(n-i)!) mod p,那么我们只需要计算n!*(i!*(n-i))^(p-2) mod p。

参考代码:

#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-10;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const int MAXN=1e6+50;
typedef __int64 LL;

LL f[MAXN],a,b,n;

bool is_excellent(int x)
{
    while(x)
    {
        if(x%10!=a&&x%10!=b)
            return false;
        x/=10;
    }
    return true;
}

LL fastmod(LL b,LL c,LL mod)//b^c%mod
{
    LL re=1,base=b;
    while(c)
    {
        if(c&1)
            re=((re%mod)*(base%mod))%mod;
        base=((base%mod)*(base%mod))%mod;
        c>>=1;
    }
    return re%mod;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
    f[0]=1;
    f[1]=1;
    for(int i=2;i<=1e6;i++)
        f[i]=(f[i-1]*i)%MOD;
    while(scanf("%I64d%I64d%I64d",&a,&b,&n)!=EOF)
    {
        LL ans=0;
        for(int i=0;i<=n;i++)
        {
            int num=a*i+b*(n-i);
            if(is_excellent(num))
            {
                //DEBUG;
                LL t=f[n];
                t=(t*fastmod(f[i],MOD-2,MOD))%MOD;
                t=(t*fastmod(f[n-i],MOD-2,MOD))%MOD;
                ans=(ans+t)%MOD;
            }
        }
        printf("%I64d\n",ans%MOD);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 11:44:54

CodeForces 300C Beautiful Numbers(乘法逆元/费马小定理+组合数公式+快速幂)的相关文章

BZOJ_[HNOI2008]_Cards_(置换+Burnside引理+乘法逆元+费马小定理+快速幂)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1004 共n个卡片,染成r,b,g三种颜色,每种颜色的个数有规定.给出一些置换,可以由置换得到的染色方案视为等价的,求等价类计数. 分析 给出置换求等价类计数,用Burnside引理:等价类计数=(每一个置换不动点的和)/置换数.(不知道的建议去看白书) 其中不动点是指一个染色方案经过置换以后染色与之前完全相同. 1.求不动点个数. 不动点的话同一个循环内的每一个点的颜色必须相同(否则不同颜色

hdu1576-A/B-(同余定理+乘法逆元+费马小定理+快速幂)

A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10383    Accepted Submission(s): 8302 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). Input 数据的第一行是一个

51nod A 魔法部落(逆元费马小定理)

A 魔法部落 小Biu所在的部落是一个魔法部落,部落中一共有n+1个人,小Biu是魔法部落中最菜的,所以他的魔力值为1,魔法部落中n个人的魔法值都不相同,第一个人的魔法值是小Biu的3倍,第二个人的魔法值是第一个人的3倍,以此类推. 现在小Biu想知道整个部落的魔法值和是多少?由于答案比较大,请把答案对1e9+7取模之后输出. 收起 输入 输入一个数N(0 <= N <= 10^9) 输出 输出:整个部落的魔法值和模1e9+7. 数据范围 对于20%的数据,n<=100: 对于40%的数

Codeforces 300C Beautiful Numbers 【组合数】+【逆元】

<题目链接> 题目大意: 给出a和b,如果一个数每一位都是a或b,那么我们称这个数为good,在good的基础上,如果这个数的每一位之和也是good,那么这个数是excellent.求长度为n的excellent数的个数mod(1e9+7). 解题分析: 我们可以枚举a的个数m,所以b的个数为(n-m),然后判断这种情况是否可行,即,是否满足a*m+b*(n-m)为good number ,如果满足的话,则答案加上C(n,m).因为n很大,并且在计算组合数的过程中,需要除以很大的数,所以需要求

[CodeVs1515]跳(lucas定理+费马小定理+乘法逆元)

嘿嘿嘿好久没写数学题了,偶尔看到一道写一写... 题目大意:一个(n+1)*(m+1)[0<=n, m<=10^12,n*m<=10^12]的矩阵,C(0,0)=1,C(x,y)=C(x-1,y)+C(x,y-1),求从0,0走到n,m路上最小权值(即为前面的C)和mod 10^9+7. 看到这个C(x,y)=C(x-1,y)+C(x,y-1),第一反应就是杨辉三角,所以这个矩阵其实就是一个由组合数组成的矩阵,第i行第j列的权值为C(i+j,j)[注意这个矩形起点是(0,0)]. 我们可

【日常学习】乘法逆元&amp;&amp;欧拉定理&amp;&amp;费马小定理&amp;&amp;欧拉函数应用&amp;&amp;常大学霸

转载请注明出处 [ametake版权所有]http://blog.csdn.net/ametake欢迎来看看 今天花了一个多小时终于把乘法逆元捣鼓明白了 鉴于我拙计的智商抓紧把这些记录下来 在此本栏目鸣谢里奥姑娘和热心网友himdd的帮助和支持 那么正文开始··· 逆元是干什么的呢? 因为(a/b)mod p ≠(a mod p)/(b mod p) 我们需要想一种方法避免高精 那就是把除法转化为乘法 因为(a*b) mod p = ( a mod p ) *( b mod p ) 怎么转化呢?

费马小定理 求乘法逆元

//P3811 [模板]乘法逆元 #include<bits/stdc++.h> using namespace std; inline void write(long long X) { if(X<0) {X=~(X-1); putchar('-');} if(X>9) write(X/10); putchar(X%10+'0'); } long long qpow(long long n,long long m,long long mod) { long long ans=1;

HDU - 1576(费马小定理求逆元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576 A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9278    Accepted Submission(s): 7452 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%99

[bzoj5118]Fib数列2_费马小定理_矩阵乘法

Fib数列2 bzoj-5118 题目大意:求Fib($2^n$). 注释:$1\le n\le 10^{15}$. 想法:开始一看觉得一定是道神题,多好的题面啊?结果...妈的,模数是质数,费马小定理就tm完事了,将fib数列的通项公式列出来然后费马小定理... 最后,附上丑陋的代码... ...(照着郭爷一顿瞎jb敲) #include <iostream> #include <cstdio> #include <cstring> #include <algo