UVA - 11806 Cheerleaders

题目

思路:

还不清楚正确的做法是怎样。

自己的做法就是容斥。

这个MOD不是素数,但是k较小可以分解素因子来计算c(i, j)而不至于溢出。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e6 + 7;
const double eps = 1e-8;
const double PI = acos(-1.0);

int n, m, k;

vi prime, cap;

void get_prime(int sz){
	prime.clear();
	bitset<MAXN> isnotprime;
	for(int i = 2; i <= sz; i++){
		if(!isnotprime[i])
			prime.push_back(i);
		for(int j = i + i; j <= sz; j += i)
			isnotprime[j] = 1;
	}
}

void divide(int x, int d){
	for(int i = 0; i < (int)prime.size() && prime[i] <= x; i++)
		while(x % prime[i] == 0){
			cap[i] += d;
			x /= prime[i];
		}
}

ll c(int a, int b){
	if(a < b)
		return 0;
	cap.clear();
	cap.resize(prime.size());
	for(int i = a - b + 1; i <= a; i++)
		divide(i, 1);
	for(int i = 2; i <= b; i++)
		divide(i, -1);
	ll res = 1;
	for(int i = 0; i < (int)cap.size(); i++)
		while(cap[i]--)
			res = (res * prime[i]) % MOD;
	return res;
}

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(10) << fixed;
	get_prime(500);
	int times;
	cin >> times;
	for(int t = 1; t <= times; t++){
		cin >> n >> m >> k;
		ll res = 0, sum = n * m;
		res = (res + c(sum, k)) % MOD; 
		res = (((res - 2 * c(sum - n, k)) % MOD + MOD - 2 * c(sum - m, k)) % MOD + MOD) % MOD;
		res = (((res + 4 * c(sum - n - m + 1, k)) % MOD + c(sum - n - n, k)) % MOD + c(sum - m - m, k)) % MOD;
		res = ((res - 2 * c(sum - n - n - m + 2, k)) % MOD + MOD - 2 * c(sum - n - m - m + 2, k) % MOD + MOD) % MOD;
		res = (res + c(sum - n - m - n - m + 4, k)) % MOD;
		cout << "Case " << t << ": ";
		cout << res << endl;
	}
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}

 

未来可期。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值