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);
} 
posted @ 2020-04-14 10:40  Shiina_Mashiro  阅读(118)  评论(0编辑  收藏  举报