Codechef CNTDSETS Counting D-sets
Link
为了防止算重,我们可以强制每一维的最小坐标都达到下限。
那么直径的限制也就变成了至少存在一个维度的最大坐标达到\(d\)。
第二个限制很好去掉,设\(f(d)\)为坐标范围为\([0,d]\)的,每一维的最小坐标都达到下限的方案数,那么答案就是\(f(d)-f(d-1)\)。
然后用容斥有多少维可能满足第一个限制,\(f(d)=\sum\limits_{i=0}^n(-1)^i{n\choose i}2^{d^i(d+1)^{n-i}}\)。
#include<cstdio>
const int P=1000000007;
int C[2001][2001];
int read(){int x;scanf("%d",&x);return x;}
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
void dec(int&a,int b){a-=b,a+=a>>31&P;}
int mul(int a,int b,int p){return 1ll*a*b%p;}
int pow(int a,int k,int p){int r=1;for(;k;k>>=1,a=mul(a,a,p))if(k&1)r=mul(a,r,p);return r;}
int f(int n,int d)
{
int sum=0;
for(int i=0;i<=n;++i) (i&1? dec:inc)(sum,mul(C[n][i],pow(2,mul(pow(d,i,P-1),pow(d+1,n-i,P-1),P-1),P),P));
return sum;
}
int main()
{
for(int i=0;i<=2000;++i) for(int j=C[i][0]=1;j<=i;++j) inc(C[i][j]=C[i-1][j],C[i-1][j-1]);
for(int T=read(),n,d;T;--T) n=read(),d=read(),printf("%d\n",(f(n,d)-f(n,d-1)+P)%P);
}