SOJ-2704(组合数取余C(n, m))

【题目描述】求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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值