• 【题解】Counting D-sets(容斥+欧拉定理)


    【题解】Counting D-sets(容斥+欧拉定理)

    没时间写先咕咕咕。

    vjCodeChef - CNTDSETS

    就是容斥,只是难了一二三四五(dots inf)

    题目大意:

    给定你一个(n)维空间,问你这个空间内有多少个点集满足两点间最大的切比雪夫距离为(d)。两个点集不同,当且仅当两个点集无法通过平移而想等。

    转化1

    考虑最后那个限制,平移想等的限制,受这道题的启发【题解】At2370 Piling Up,我们考虑钦定每一维的(0)点都有点坐落,这样就钦定了一个基准,问题就转变成了要求每维都有(0),且存在某个点的某维坐标为(d),且(d)是所有数里最大的。

    转化2

    此类题有一个套路,就是当它钦定最大最小为(d)的时候的方案数,可以等于([0,d])的随机分配(-[0,d-1])的随机分配,这样减出来的方案就保证了一定有点在(d)空间的边界上,不然一定会被减去。

    转化3

    所以我们答案就是(f(d)-f(d-1)),其中(f(d))表示(n)维空间的每维在([0,d])中随意分配坐标的方案数。此时我们发现仍然有问题,因为我们还没有钦定每一维有(0)

    考虑我们如何钦定每一维都有零,显然不能一个组合数直接钦定,因为可能一个点的坐标有多个(0),这个情况我们考虑不到。但是可以发现每一维本质相同的(意思是可以通过组合数来计算方案),所以可以(O(n))容斥。考虑我们容斥什么,我们容斥钦定每至少i维没有(0),最后我们要的是(0)维没有(0)

    转换4

    我们看一个点的坐标,写成这个形式(p(x_1,x_2,x_3,x_4dots x_n),x_iin [0,d],x_i in N^+),那么由(p)构成的点集的方案是多少呢,我想啊想想不出来就去看题解去了。题解告诉我,这个的方案数是

    [2^{(d+1)^n} ]

    傻逼了。其实很简单,总共有((d+1)^n)个点,枚举每个点放不放即可,注意包括了一个也不放的方案。

    那么如何钦定至少(i)没有(0)呢?很简单,钦定(x_iin[1,d])就好了。那么这个的方案就是

    [{n choose i}2^{d^i(d+1)^{n-i}} ]

    乘上一个组合数枚举哪些维度没有(0)

    所以最终(f(x)=)

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

    所以最终答案(=f(d)-f(d-1))

    转换5

    看答案那个式子,你发现你要到指数上面取膜,你很害怕,因为你好像不知道指数上取膜的运算规则。这就(naive)了,模数是(1e9+7)是个质数,现在你发现欧拉定理有用了,因为

    [a^{phi(p)} equiv 1 mod p ]

    而质数中,(phi(p)=p-1)。所以你在指数上就直接对(1e9+6)取膜就好了。

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    const int mod=1e9+7;
    inline int Pow(int base,const int&p){
          register int ret=1;
          for(register int t=p;t;t>>=1,base=1ll*base*base%mod)
    	    if(t&1) ret=1ll*ret*base%mod;
          return ret;
    }
    
    const int mod2=mod-1;
    inline int zhiPow(int base,const int&p){
          register int ret=1;
          for(register int t=p;t;t>>=1,base=1ll*base*base%mod2)
    	    if(t&1) ret=1ll*ret*base%mod2;
          return ret;      
          
    }
    
    const int maxn=1e3+5;
    int jc[maxn],inv[maxn];
    int n,d;
    inline int c(const int&n,const int&m){
          if(n<m)return 0;
          return 1ll*jc[n]*inv[m]%mod*1ll*inv[n-m]%mod;
    }
    inline int F(const int&x){
          register int ret=0;
          for(register int t=0,delta;t<=n;++t){
    	    delta=1ll*c(n,t)*Pow(2,(1ll*zhiPow(x,t)*zhiPow(x+1,n-t))%mod2)%mod;
    	    if(t&1) delta=mod-delta;
    	    ret=(ret+delta)%mod;
          }
          return ret;
    }
    
    
    int main(){
    #ifndef ONLINE_JUDGE
          freopen("in.in","r",stdin);
          //freopen("out.out","w",stdout);
    #endif
          int T=qr();
          jc[0]=inv[0]=1;
          for(register int t=1;t<maxn;++t)
    	    jc[t]=1ll*jc[t-1]*t%mod,inv[t]=Pow(jc[t],mod-2);
          while(T--){
    	    n=qr(),d=qr();
    	    cout<<((F(d)-F(d-1))%mod+mod)%mod<<endl;
          }
          return 0;
    }
    
    
    Status Accepted
    Memory 15257kB
    Length 1546
    Lang C++14(gcc 6.3)
    Submitted 2019-06-13 17:44:16
    Shared Yes
    RemoteRunId 24729181
  • 相关阅读:
    [JSBSim]基于winsocket2的TCPUDP使用例子
    [转][JSBSim]JSBSim的使用--飞行控制组件及其配置
    [原][译][osg][osgEarth]飞行模拟软件JSBSim的操作(FGFCS类)
    [原][JSBSim]基于qt代码实现:TCP|UDP与飞行模拟软件JSBSim的通信,现实模型飞行!
    Linux mysql添加用户,删除用户,以及用户权限
    Linux启动/停止/重启Mysql数据库的方法
    Linux中vi编辑器的使用详解
    安装mysql问题解决
    centos6.5下修改文件夹权限和用户名用户组
    mysql启动时报错:Starting MySQL... ERROR! The server quit without updating PID file (/opt/mysql/data/mysql.pid) 的解决方法
  • 原文地址:https://www.cnblogs.com/winlere/p/11018245.html
Copyright © 2020-2023  润新知