• 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} floor} sum_{p_{2}}^{ lfloor frac{m_{2}}{gd} floor}  cdots  sum_{p_{n}}^{ lfloor frac{m_{n}}{gd} floor} (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} floor} sum_{p_{2}}^{lfloor frac{m_{2}}{d} floor} cdots sum_{p_{n}}^{lfloor frac{m_{n}}{d} floor} (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} floor (2m_{i} - (lfloor frac{m_{i}}{d} floor  + 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} floor )  sum_{j=0}^{n}f_{j}d^{j}$
      • $ = sum_{d} ( Pi_{i=1}^{n} 2^{-1} lfloor frac{m_{i}}{d} floor ) 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} floor $是一个常数,所以$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
        ",(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
        ",(solve()+mod)%mod);
        90     }
        91     return 0;
        92 }
        View Code
  • 相关阅读:
    Windows Phone 7 中常用Task
    设置Highchart柱子最大宽度( 让 highcharts支持maxPointWidth属性)
    Asp.Net MVC 使用FileResult导出Excel数据文件
    js获取网页高度
    使用window.addEventListener 和 window.attachEvent 判断浏览器
    slimscroll滚动条插件简单用法
    js中如何快速获取数组中的最大值最小值
    js 判断浏览器类型
    python使用ldap进行用户认证
    关于go声明切片的一些疑问
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10376609.html
Copyright © 2020-2023  润新知