链接: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;
}