思路:
还不清楚正确的做法是怎样。
自己的做法就是容斥。
这个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;
}
未来可期。