牛客IOI周赛17-普及组 莫的难题(数学)

链接:https://ac.nowcoder.com/acm/contest/5881/B
来源:牛客网

题目描述
埋和莫曾经是好朋友。埋是文科学霸,而莫却只是一个 OI 蒟蒻。一天,埋碰到一道难题跑来问莫。题目是这样的:有五个数字,分别是 5、2、1、3、9.莫可以取任意数字,每个数字可以取无限次。如:取两个 5,则组合为:55;取 2 与 1,则组合为:21。现在要问你所有组合中第 C(n, m)%1e9+7 (n>=m) 个数有多大?
输入描述:
第 1 行一个数 t,表示询问的次数
接下来 t 行,每行两个数 n, m;详情见题目描述。
数据范围:
对于20%的数据,保证t=1
对于10%的数据,保证n=m
对于所有数据,保证
1<=t<=1000
1<=m<=n<=100
输出描述:
t行,每行一个数字,表示所有组合中第 C(n, m)%1e9+7 (n>=m) 个大的数?
示例1
输入
复制
2
3 2
4 3
输出
复制
3
5

思路:
1位有5个
2位有25个
3位有125个。。。
先确定位数,再确定你用这些数可以拼成该位上多大的数。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
 
typedef long long ll;
const int maxn = 105;
const int mod = 1e9 + 7;
ll fac[maxn],inv[maxn],f[maxn];
map<int,int>mp;
 
ll qpow(ll a,ll b)
{
     
    ll res = 1;
    while(b)
    {
     
        if(b & 1)
        {
     
            res = (res * a) % mod;
        }
        a = (a * a) % mod;
        b = b >> 1;
    }
    return res % mod;
}
 
void init()
{
     
    mp[4] = 9;mp[0] = 1;mp[1] = 2;mp[2] = 3;mp[3] = 5;
    fac[0] = 1;
    inv[0] = 1;
    for(int i = 1;i <= maxn - 2;i++)
    {
     
        fac[i] = (fac[i - 1] * i) % mod;
        inv[i] = qpow(fac[i],mod - 2);
    }
}
 
ll C(ll n,ll m)
{
     
    if(m > n || m < 0)
        return 0;
    return fac[n] * ((inv[n - m] * inv[m]) % mod) % mod;
}
 
void get(int num) {
     
    int ans[20];
    memset(ans,0,sizeof(ans));
    int len = 1;
    ll cnt = 5;
    while(num > cnt) {
     
        num -= cnt;
        cnt = cnt * 5;
        len++;
    }
    cnt /= 5;
    for(int i = 1;i <= len;i++) {
     
        int ci = (num - 1) / cnt;
        ans[i] = mp[ci];
        num -= ci * cnt;
        cnt /= 5;
    }
    for(int i = 1;i <= len;i++) {
     
        printf("%d",ans[i]);
    }
    printf("\n");
}
 
int main() {
     
    init();
    int T;scanf("%d",&T);
    while(T--) {
     
        int n,m;scanf("%d%d",&n,&m);
        int num = C(n,m);
        get(num);
    }
    return 0;
}

你可能感兴趣的:(#,其他比赛题目)