【Codechef】CNTDSETS

题面

vjudge

求出\(n\)维空间中的点集数目,满足其直径恰好为\(D\)。点集的直径是点集中最远一对
点的切比雪夫距离。如果两个点集可以通过平移相互转换,则这两个点集是相同的。

题解

直接蒯Anson爷的题解了:

平移的限制可以理解为每一维都存在该维坐标为\(0\)的点(认为所有坐标都是非负整数)。这样一来,距离限制也可以转化为至少有一维的最大坐标为\(D\)

考虑计算最大值小于等于\(x\)的方案\(f(x)\),容斥“每一维都存在0“。
答案就是

\[Ans=f(D)-f(D-1)\\ f(D)=\sum_{i=0}^n(-1)^i{n\choose i}2^{d^i(d+1)^{n-i}} \]

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar(); 
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
    return w * data; 
} 
const int Mod = 1e9 + 7, Phi = Mod - 1; 
int fpow(int x, int y, int m) { 
	int res = 1; 
	while (y) {
		if (y & 1) res = 1ll * res * x % m; 
		x = 1ll * x * x % m; 
		y >>= 1; 
	} 
	return res; 
}
const int MAX_N = 2e3 + 5, MAX = 2e3; 
int N, D, C[MAX_N][MAX_N]; 
int f(int d) { 
	int res = 0, p = 1; 
	for (int i = 0; i <= N; i++) { 
		res = (res + 1ll * p * C[N][i] % Mod *
			   fpow(2, 1ll * fpow(d, i, Phi) * fpow(d + 1, N - i, Phi) % Phi, Mod)) % Mod; 
		p = Mod - p; 
	} 
	return res; 
} 
int main () {
	for (int i = 0; i <= MAX; i++) C[i][0] = C[i][i] = 1; 
	for (int i = 1; i <= MAX; i++)
		for (int j = 1; j < i; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % Mod; 
	int T = gi(); 
	while (T--) { 
		N = gi(), D = gi(); 
		printf("%d\n", (f(D) - f(D - 1) + Mod) % Mod); 
	} 
    return 0; 
} 
posted @ 2020-01-15 22:11  heyujun  阅读(169)  评论(0编辑  收藏  举报