【题目描述】求C(n, m) % k 是否等于0,如果等于0,输出“Yes”,否则输出“No”。
【题目分析】首先找出k中各个素数约数的个数,这里用简易素数的筛法:
for (i = 2; i * i <= c; ++i) {
if (c % i == 0) {
wo[index].x = i;
wo[index].num1 = wo[index].num2 = 0;
while (c % i == 0) {
wo[index].num1++;
c /= i;
}
++index;
}
}
if (c != 1) {
wo[index].x = c;
wo[index].num2 = 0;
wo[index].num1 = 1;
++index;
}
因为
C(n, m) = n! / ((n-m)!*m!),所以计算n!中各个约数的个数,减去
(n-m)!和m!约数的个数,如果k中
相应的约数个数小于等于前面的,就“Yes”。
计算n!中约数x的个数可以如下计算
for (j = wo[i].x; j <= a; j *= wo[i].x) {
wo[i].num2 += a / j;
}
十分经典的数论题目,源代码如下:
struct my
{
ll x;
ll num1;
ll num2;
} wo[10005];
int main()
{
ll i, j;
ll t;
cin>>t;
while (t--) {
ll a, b, c;
ll index = 0;
scanf("%lld%lld%lld", &a, &b, &c);
for (i = 2; i * i <= c; ++i) {
if (c % i == 0) {
wo[index].x = i;
wo[index].num1 = wo[index].num2 = 0;
while (c % i == 0) {
wo[index].num1++;
c /= i;
}
++index;
}
}
if (c != 1) {
wo[index].x = c;
wo[index].num2 = 0;
wo[index].num1 = 1;
++index;
}
for (i = 0; i < index; ++i) {
for (j = wo[i].x; j <= a; j *= wo[i].x) {
wo[i].num2 += a / j;
}
for (j = wo[i].x; j <= b; j *= wo[i].x) {
wo[i].num2 -= b / j;
}
for (j = wo[i].x; j <= a - b; j *= wo[i].x) {
wo[i].num2 -= (a - b) / j;
}
}
for (i = 0; i < index; ++i)
if (wo[i].num1 > wo[i].num2)
break;
printf("%s\n", i == index ? "Yes" : "No");
}
return 0;
}