Find the number of trailing zeroes for the following function:
nCr * pq
where n, r, p, q are given. For example, if n = 10, r = 4, p = 1, q = 1, then the number is 210 so, number of trailing zeroes is 1.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case contains four integers: n, r, p, q (1 ≤ n, r, p, q ≤ 106, r ≤ n).
Output
For each test case, print the case number and the number of trailing zeroes.
Sample Input
2
10 4 1 1
100 5 40 5
Sample Output
Case 1: 1
Case 2: 6
题意:求 组合数C(n,r) * p^q 末尾0的个数。
思路:又是求末尾0的个数,末尾0就和 10 , 2 ,5有关,所以我们就可以用一个前缀和记录每一个数之前,10,5,2出现的次数。对于组合数 C(n,r) = n! / r ! * (n-r) ! emmm....好像知道这么多就够了吧。
代码如下:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1000010
using namespace std;
int num10[N],num5[N],num2[N];
void init() //打表,算前缀和
{
for(int i=1; i<N; i++)
{
int x=i;
while(x%10==0) //这个数含有多少个10,下面同理,
{
x/=10;
num10[i]++;
}
while(x%5==0)
{
x/=5;
num5[i]++;
}
while(x%2==0)
{
x/=2;
num2[i]++;
}
num10[i]+=num10[i-1]; //算前缀和
num5[i]+=num5[i-1];
num2[i]+=num2[i-1];
}
}
int solve(int n,int r,int p,int q)
{
int a10=num10[n]-num10[r]-num10[n-r];//组合数含有10,5,2的个数
int a5=num5[n]-num5[r]-num5[n-r];
int a2=num2[n]-num2[r]-num2[n-r];
a10+=q*(num10[p]-num10[p-1]); //p^q次幂含有的10,5,2的个数
a5+=q*(num5[p]-num5[p-1]);
a2+=q*(num2[p]-num2[p-1]);
return a10+min(a2,a5);//10的个数 + min(2,5的个数)
}
int main()
{
init();
int t,cas=1;
scanf("%d",&t);
while(t--)
{
int n,r,p,q;
scanf("%d%d%d%d",&n,&r,&p,&q);
printf("Case %d: %d\n",cas++,solve(n,r,p,q));
}
return 0;
}