CodeForces 300C --数论

A - A

Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u

Submit Status Practice CodeForces 300C

Description

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 Input

Input

1 3 3

Output

1

Input

2 3 10

Output

165

这道题的想法很简答,枚举a的个数,判断a*i+b*(n-i)是不是一个good数,如果是的话,那么i个a + n-i个b就可以组成excellent数。然后求组合数C(i,n)。问题是C(i,n)很不好求。因为C(i,n)=(n!)/[(i!*(n-i)!],本身数据量就很大,而mod 1e9后,直接计算会造成精度的损失。这里用到两个知识:费马小定理 乘法逆元,在加一个简单的快速幂。

(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=1x*(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<iostream>
#include<stdio.h>
//#define prim 1000000000+7
using namespace std;
int a,b,n;
const long long prim=1e9+7;
long long dp[1000005];
bool exce(long long sum)
{
    //cout<<sum<<endl;
    while(sum>0)
    {
        if(sum%10!=a&&sum%10!=b)
            return false;
        sum/=10;
    }
    return true;
}
long long int comb(long long i)
{
   // if(i==0||i==1) return 1;
    long long int _i;
    _i=dp[i];
    long long int _ans=1;
    long long int p=prim-2;
    while(p>0)
    {
        if(p&1)
            _ans=_ans*_i%prim;
        _i=_i*_i%prim;
        p=p>>1;

    }
    return _ans%prim;

}
int main()
{
    cout<<prim-2<<endl;
    dp[0]=1;

    //printf("%I64d\n%I64d",dp[1000000],dp[1000000-1]);
    long long int ans=0;
    scanf("%d%d%d",&a,&b,&n);
    for(long long int i=1;i<=n;i++)
    {
        dp[i]=(dp[i-1]*i)%(prim);
    }
    for(long long int i=0;i<=n;i++)
    {
        if(exce(a*i+b*(n-i)))
        {
            long long comi=comb(i);
            long long comni=comb(n-i);
            //cout<<comi<<endl<<comni<<endl;
            ans+=dp[n]*comi%prim*comni%prim;
        }
    }
    printf("%I64d\n",ans%prim);
    return 0;
}

这里我要说明一下,你会发现我的代码里面有两个prim,一个是constant,一个是#define,经过实践检验,我发现用常变量是正确的,用宏是错误的。虽然我现在还不知道是为什么,但是应该注意到这一点,以后涉及到计算的一律用常变量。再用宏我就是脑袋有坑。
时间: 2024-10-11 18:47:59

CodeForces 300C --数论的相关文章

CodeForces 300C 最短路

A Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 300C Description Vitaly is a very weird man. He's got two favorite digits a and b. Vitaly calls a positive integer good, if the decimal

Trailing Loves (or L&#39;oeufs?) CodeForces - 1114C (数论)

大意: 求n!在b进制下末尾0的个数 等价于求n!中有多少因子b, 素数分解一下, 再对求出所有素数的最小因子数就好了 ll n, b; vector<pli> A, res; void factor(ll x) { int mx = sqrt(x+0.5); REP(i,2,mx) if (x%i==0) { int t = 0; while (x%i==0) x/=i,++t; A.pb(pli(i,t)); } if (x>1) A.pb(pli(x,1)); } int main

CodeForces 396A 数论 组合数学

题目:http://codeforces.com/contest/396/problem/A 好久没做数论的东西了,一个获取素数的预处理跟素因子分解写错了,哭瞎了,呵呵, 首先ai最大值为10^9,n为500,最坏的情况 m最大值为500个10^9相乘,肯定不能获取m了,首选每一个ai肯定是m的一个因子,然后能分解就把ai给分解素因子,这样全部的ai都分解了  就能得到m的 所有素因子 以及 所有素因子的个数,题目求的 是n个因子的 不同序列的个数,所以每次 只能选出n个因子,这n个因子由素因子

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

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem F (Codeforces 831F) - 数论 - 暴力

Vladimir wants to modernize partitions in his office. To make the office more comfortable he decided to remove a partition and plant several bamboos in a row. He thinks it would be nice if there are n bamboos in a row, and the i-th from the left is a

CodeForces 359D (数论+二分+ST算法)

题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=47319 题目大意:给定一个序列,要求确定一个子序列,①使得该子序列中所有值都能被其中一个值整除,②且子序列范围尽可能大(r-l尽可能大). 解题思路: 对于要求1,不难发现只有min(L,R)=gcd(L,R)时才行.其中gcd是L,R范围内的最大公约数,min是L,R范围内的最小值. 对于要求2,传统思路是r-l从大到小枚举,每次确定一个(L,R)范围,进行判

CodeForces 1202F(数论,整除分块)

题目 CodeForces 1213G 做法 假设有\(P\)个完整的循环块,假设此时答案为\(K\)(实际答案可能有多种),即每块完整块长度为\(K\),则\(P=\left \lfloor \frac{N}{K} \right \rfloor\) 假设循环快中有\(p_a,p_b\)个\(A\)和\(B\),则 \(p_a\cdot P\le a\Longrightarrow p_a\le \left \lfloor \frac{a}{P} \right \rfloor\) \(p_a\cd

Codeforces 396A 数论,组合数学

题意:给一个a数组,求b 数组的方案数,但是要求两者乘积相同. 分析: 不可能将它们乘起来,对于每个数质因数分解,得到每个质因子个数,遍历这些质因子,将某个质因子放到 对应的盒子里面,可以不放,方案数就是一个组合数,用插板法. 这里的素数板子挺好的,一方面可以用来判断,一方面存起来. 组合数,可以考虑用乘法逆元. 每个质因子个数hash一下. #include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; #defi

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很大,并且在计算组合数的过程中,需要除以很大的数,所以需要求