zoukankan      html  css  js  c++  java
  • bzoj3434 [Wc2014]时空穿梭

    式子的推导网上有很多dalao写的都很好,就不再赘述了。

    有两点是我没有想到的,再次写一下。

    首先就是初始的式子。不知道直角三角形斜边上整数点个数=gcd(a,b)+1,更没有拓展到多维。

    第二就是划出来60分的式子之后的优化,把后边的关于T的多项式的系数通过O(n2)时间算了出来$O(n^2*m)->O(n^3*sqrt{m})$

    十分巧妙。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define N 100500
     7 #define mod 10007
     8 using namespace std;
     9 int C[N][25],mu[N],h[N],nn,prime[N],tot,vis[N],g[25][N],pw[N][25],sum[25][25][N];
    10 void init(){
    11     C[0][0]=1;
    12     for(int i=1;i<=100000;i++){
    13         C[i][0]=1;
    14         for(int j=1;j<=20&&j<=i;j++)
    15             C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    16     }
    17     mu[1]=1;h[++nn]=1;
    18     for(int i=2;i<=100000;i++){
    19         if(!vis[i]){
    20             prime[++tot]=i;
    21             mu[i]=-1;
    22         }
    23         for(int j=1;j<=tot&&i*prime[j]<=100000;j++){
    24             vis[i*prime[j]]=1;
    25             if(i%prime[j]==0){
    26                 mu[i*prime[j]]=0;
    27                 break;
    28             }
    29             mu[i*prime[j]]=-mu[i];
    30         }
    31         if(mu[i])h[++nn]=i;
    32     }
    33     for(int k=2;k<=20;k++){
    34         for(int i=1;i<=100000;i++)
    35             for(int j=1;j<=nn&&h[j]*i<=100000;j++)
    36                 (g[k][i*h[j]]+=mu[h[j]]*C[i-1][k-2]+mod)%=mod;
    37     }
    38     for(int i=1;i<=100000;i++){
    39         pw[i][0]=1;
    40         for(int j=1;j<=11;j++)pw[i][j]=pw[i][j-1]*i%mod;
    41     }
    42     for(int k=1;k<=20;k++)
    43         for(int j=0;j<=11;j++)
    44             for(int i=1;i<=100000;i++)
    45                 sum[k][j][i]=(sum[k][j][i-1]+g[k][i]*pw[i][j]%mod)%mod;
    46 }
    47 int T,n,c,m[25],ans,f[25];
    48 void work(int x){
    49     memset(f,0,sizeof f);f[0]=1;
    50     for(int i=1;i<=n;i++){
    51         for(int j=i;j>0;j--)
    52             f[j]=(f[j]*2%mod*m[i]%mod-f[j-1]*(m[i]/x+1)%mod+mod)%mod;
    53         f[0]=f[0]*2*m[i]%mod;
    54     }
    55 }
    56 int main(){
    57     init();
    58     scanf("%d",&T);
    59     while(T--){
    60         scanf("%d%d",&n,&c);ans=0;
    61         for(int i=1;i<=n;i++)scanf("%d",&m[i]);
    62         sort(m+1,m+n+1);
    63         for(int i=1,pos;i<=m[1];i=pos+1){
    64             pos=N;
    65             for(int j=1;j<=n;j++)pos=min(pos,m[j]/(m[j]/i));
    66             int now=1;
    67             for(int j=1;j<=n;j++)
    68                 now=(now*(m[j]/i)%mod*5004%mod);
    69             work(i);
    70             for(int j=0;j<=n;j++)
    71                 (ans+=now*f[j]%mod*(sum[c][j][pos]-sum[c][j][i-1]+mod)%mod)%=mod;
    72         }
    73         printf("%d
    ",ans);
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    Linux编程make命令(转)
    如何处理Global symbol * requires explicit package name编译错误,以及use strict用法
    6235与旧版本的区别
    Linux下动态链接库的使用
    MTK Socket学习——HTTP请求
    指针和指针的引用
    VC/MFC Combo Box控件的用法
    makefile教程
    常用数据类型使用转换详解
    Linux发送与接收信息
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8213588.html
Copyright © 2011-2022 走看看