bzoj3434[wc2014]时空穿梭

题目描述 


输入格式

第一行包含一个正整数T,表示有T组数据求解
每组数据包含两行,第一行包含两个正整数N,C(c>=2),分别表示空间的
维数和需要选择的暂停点个数
第二行包含N个正整数,依次表示M1,M2....Mn


输出格式

有T行,每行一个非负整数,依次对应每组数据的答案。


 

  • 题解:

    • 一个$n$维向量$(p_{1},p_{2}, \cdots ,p_{n})$上的整点个数为:$gcd(p_{1},p_{2}, \cdots , p_{n})+1$
    • 可以枚举这个n维向量,考虑到向量在空间里面自由移动也是不同的方案:
    • $ans = \sum^{m_{1}}_{p_{1}} \sum^{m_{2}}_{p_{2}} \cdots \sum^{m_{n}}_{p_{n}}(m_{1}-p_{1})(m_{2}-p_{2}) \cdots (m_{n}-p_{n}) C_{gcd(p1,p2, \cdots ,p_{n}) - 1}^{c - 2} $
    • 枚举因子,反演得:
    • $ \sum_{d} C_{d-1}^{c-2} \sum_{g} \mu(g) \sum_{p_{1}}^{ \lfloor \frac{m_{1}}{gd} \rfloor} \sum_{p_{2}}^{ \lfloor \frac{m_{2}}{gd} \rfloor}  \cdots  \sum_{p_{n}}^{ \lfloor \frac{m_{n}}{gd} \rfloor} (m_{1}-p_{1}gd) (m_{2}-p_{2}gd) \cdots (m_{n}-p_{n}gd)  $
    • $ = \sum_{d} \sum_{g|d} C_{d-1}^{c-2} \mu(\frac{d}{g})  \sum_{p_{1}}^{\lfloor \frac{m_{1}}{d} \rfloor} \sum_{p_{2}}^{\lfloor \frac{m_{2}}{d} \rfloor} \cdots \sum_{p_{n}}^{\lfloor \frac{m_{n}}{d} \rfloor} (m_{1}-p_{1}d)(m_{2}-p_{2}d) \cdots (m_{n}-p_{n}d)$
    • 等差数列求和:
    • $ = \sum_{d} \sum_{g|d} C_{d-1}^{c-2} \mu(\frac{d}{g}) ( \Pi_{i=1}^{n} 2^{-1} \lfloor  \frac{m_{i}}{d} \rfloor (2m_{i} - (\lfloor \frac{m_{i}}{d} \rfloor  + 1 ) d ) )$
    • 其中2^{-1}表示2的逆元;
    • 到这里是基本的化简;
    • 考虑下底分块,由于$\Pi$的部分含有d,所以需要把考虑成一个关于$d$的多项式$f$进一步化简:
    • $ = \sum_{d} \sum_{g|d} C_{d-1}^{c-2} \mu(\frac{d}{g})  (\Pi_{i=1}^{n} 2^{-1} \lfloor  \frac{m_{i}}{d} \rfloor )  \sum_{j=0}^{n}f_{j}d^{j}$
    • $ = \sum_{d} ( \Pi_{i=1}^{n} 2^{-1} \lfloor \frac{m_{i}}{d} \rfloor ) \sum_{j=0}^{n} f_{j} d^{j} \sum_{g|d} C_{d-1}^{c-2} \mu(\frac{d}{g})  $ 
    • 注意到分块后$\lfloor \frac{m_{i}}{d} \rfloor $是一个常数,所以$f_{j}$及其以前的部分全都是常数的,后面的部分只和$d$有关,预处理前缀和即可;
    • 复杂度:$O(n^{3}\sqrt{m}    +    cnm + cmlogm )$
    •  1 #include<bits/stdc++.h>
       2 #define il inline 
       3 #define mod 10007
       4 #define iv2 5004
       5 using namespace std;
       6 const int N=15,M=100010,C=21;
       7 int T,n,c,m[N],g[C][N][M],a1[N],a2[N],f[N],fac[M],inv[M],u[M],vis[M],pr[M],pt;
       8 il int min(int x,int y){if(x<y)return x;else return y;} 
       9 il int get(int x,int y){
      10     if(x<mod&&y<mod)return x<y?0:fac[x]*inv[y]%mod*inv[x-y]%mod;
      11     else return get(x/mod,y/mod)*get(x%mod,y%mod)%mod;
      12 }
      13 il int pw(int x,int y){
      14     int re=1;x%=mod;
      15     for(;y;y>>=1,x=x*x%mod){
      16         if(y&1)re=x*re%mod;
      17     }return re;
      18 }
      19 void pre(){
      20     for(int i=fac[0]=inv[0]=1;i<=1e5;++i){
      21         fac[i]=fac[i-1]*i%mod;
      22         inv[i]=pw(fac[i],mod-2);
      23     }
      24     u[1]=1;
      25     for(int i=2;i<=1e5;++i){
      26         if(!vis[i])u[pr[++pt]=i]=-1;
      27         for(int j=1;j<=pt&&pr[j]*i<=1e5;++j){
      28             vis[i*pr[j]]=1;
      29             if(i%pr[j]==0){u[i*pr[j]]=0;break;}
      30             else u[i*pr[j]]=-u[i];
      31         }
      32     }
      33     for(int c=2;c<=20;++c)
      34     for(int i=1;i<=1e5;++i)if(u[i])
      35     for(int j=1;i*j<=1e5;++j){
      36         g[c][0][i*j]=(g[c][0][i*j]+u[i]*get(j-1,c-2))%mod;
      37     } 
      38     for(int c=2;c<=20;++c)
      39     for(int i=1;i<=11;++i)
      40     for(int j=1;j<=1e5;++j){
      41         g[c][i][j]=g[c][i-1][j]*j%mod;
      42     }
      43     for(int c=2;c<=20;++c)
      44     for(int i=0;i<=11;++i)
      45     for(int j=1;j<=1e5;++j){
      46         g[c][i][j]=(g[c][i][j]+g[c][i][j-1])%mod;
      47     }
      48 }
      49 void cal(int d){
      50     for(int i=0;i<=n;++i)a1[i]=a2[i]=0;
      51     a1[0]=1;
      52     for(int i=1;i<=n;++i){
      53         int x=(m[i]/d+1)%mod,y=2*m[i]%mod;
      54         for(int j=0;j<=i;++j){
      55             a2[j+1]=-a1[j]*x%mod;
      56             a1[j]=(a1[j]*y%mod+a2[j])%mod;
      57         }
      58     }
      59     for(int i=0;i<=n;++i)f[i]=a1[i];
      60 }
      61 int solve(){
      62     int mn=1e5,re=0;
      63     for(int i=1;i<=n;++i)mn=min(mn,m[i]);
      64     for(int i=1,lst;i<=mn;i=lst+1){
      65         int t1=1,t2=0;lst=1e5;
      66         for(int j=1;j<=n;++j){
      67             lst=min(lst,m[j]/(m[j]/i));
      68             t1=t1*(m[j]/i)%mod*iv2%mod;
      69         }
      70         cal(i);
      71         for(int j=0;j<=n;++j){
      72             t2=(t2+f[j]*(g[c][j][lst]-g[c][j][i-1])%mod)%mod;
      73         //    printf("%d\n",(g[c][j][lst]-g[c][j][i-1]+mod)%mod);
      74         }
      75         re=(re+t1*t2%mod)%mod;
      76     }
      77     return re;
      78 }
      79 int main(){
      80     #ifndef ONLINE_JUDGE
      81     freopen("bzoj3434.in","r",stdin);
      82     freopen("bzoj3434.out","w",stdout);
      83     #endif
      84     pre();
      85     scanf("%d",&T);
      86     while(T--){
      87         scanf("%d%d",&n,&c);
      88         for(int i=1;i<=n;++i)scanf("%d",&m[i]);
      89         printf("%d\n",(solve()+mod)%mod);
      90     }
      91     return 0;
      92 }
      View Code

       

 

posted @ 2019-02-14 19:40  大米饼  阅读(188)  评论(0编辑  收藏  举报