• The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest


    https://www.jisuanke.com/contest/3098?view=challenges

    优质题解

    https://acm.ecnu.edu.cn/wiki/index.php?title=2019_ICPC_China_Nanchang_Invitational_Programming_Contest

    A. Attack

    斯坦纳树

    之后再补

    B. Polynomial

    若干个n次函数相加 f(0)+f(1)+...+f(k)

    自然数幂和  a_{d} * ( sum of i^d ) d+1次函数

    max of d = n 即为n+1次函数

    自然数幂和 见 https://www.cnblogs.com/cmyg/p/11256321.html

    510ms

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=9999991;
     14 const int maxn=1e3+10;
     15 const int maxlen=mod+10;
     16 
     17 /**
     18 1.1~9999991 inv
     19 2.use int
     20 **/
     21 
     22 /**
     23 better way:
     24 多项式快速插值
     25 luogo5158
     26 **/
     27 
     28 ll y[maxn],n;
     29 int jie[maxlen],inv_jie[maxlen],inv_num[maxlen];
     30 //ll maxv=1e3;
     31 ll maxv=mod-1;
     32 
     33 ll mul(ll a,ll b)
     34 {
     35     ll y=1;
     36     while (b)
     37     {
     38         if (b&1)
     39             y=y*a%mod;
     40         a=a*a%mod;
     41         b>>=1;
     42     }
     43     return y;
     44 }
     45 
     46 ll cal(ll x)
     47 {
     48     ll i,u,tot,sum=0;
     49     u=1;
     50     for (i=x;i>=x-n;i--)
     51         u=u*i%mod;
     52     for (i=0;i<=n;i++)
     53     {
     54         ///1ll
     55         tot=1ll*inv_jie[i]*inv_jie[n-i]%mod *u%mod *inv_num[x-i]%mod;
     56 //        tot=inv_jie[i]*inv_jie[n-i]%mod *u%mod *mul(x-i,mod-2)%mod;
     57         if ((n-i)&1)
     58             tot=-tot;
     59         (sum+=tot*y[i])%=mod;
     60     }
     61     return (sum+mod)%mod;
     62 }
     63 
     64 int main()
     65 {
     66     ll t,m,i,p,q,vp,vq;
     67     jie[0]=1;
     68     maxv=mod-1;
     69     for (i=1;i<=maxv;i++)
     70         ///1ll
     71         jie[i]=1ll*jie[i-1]*i%mod;
     72     inv_jie[maxv]=mul(jie[maxv],mod-2);
     73     for (i=maxv-1;i>=0;i--)
     74     {
     75         inv_jie[i]=1ll*inv_jie[i+1]*(i+1)%mod;
     76         ///1~9999991 inv
     77         inv_num[i+1]=1ll*inv_jie[i+1]*jie[i]%mod;
     78     }
     79 
     80     /**
     81     inv
     82     t*(n+2*m)
     83     6000000
     84     log(9999990) 25
     85     **/
     86 
     87 
     88     scanf("%lld",&t);
     89     while (t--)
     90     {
     91         scanf("%lld%lld",&n,&m);
     92         for (i=0;i<=n;i++)
     93             scanf("%lld",&y[i]);
     94         y[n+1]=cal(n+1);
     95         n++;
     96 
     97         ///sum 1~n
     98         for (i=1;i<=n;i++)
     99             (y[i]+=y[i-1])%=mod;
    100 
    101         while (m--)
    102         {
    103             scanf("%lld%lld",&p,&q);
    104             p--;
    105             vq=q<=n?y[q]:cal(q);
    106             vp=p<=n?y[p]:cal(p);
    107             printf("%lld
    ",(vq-vp+mod)%mod);///L>=1
    108         }
    109     }
    110 
    111     return 0;
    112 }
    113 /*
    114 1
    115 3 10
    116 0 1 4 9
    117 3 5
    118 1 5
    119 
    120 
    121 1
    122 3 10
    123 5 5 5 5
    124 1 5
    125 */

    用long long,内存勉强不超。但估计在现场赛的时候,会超。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=9999991;
     14 const int maxn=1e3+10;
     15 const int maxlen=mod+10;
     16 
     17 /**
     18 1.1~9999991 inv
     19 2.use int
     20 **/
     21 
     22 /**
     23 better way:
     24 多项式快速插值
     25 luogo5158
     26 **/
     27 
     28 ll y[maxn],jie[maxlen],inv_jie[maxlen],inv_num[maxlen],n;
     29 //ll maxv=1e3;
     30 ll maxv=mod-1;
     31 
     32 ll mul(ll a,ll b)
     33 {
     34     ll y=1;
     35     while (b)
     36     {
     37         if (b&1)
     38             y=y*a%mod;
     39         a=a*a%mod;
     40         b>>=1;
     41     }
     42     return y;
     43 }
     44 
     45 ll cal(ll x)
     46 {
     47     ll i,u,tot,sum=0;
     48     u=1;
     49     for (i=x;i>=x-n;i--)
     50         u=u*i%mod;
     51     for (i=0;i<=n;i++)
     52     {
     53         tot=inv_jie[i]*inv_jie[n-i]%mod *u%mod *inv_num[x-i]%mod;
     54 //        tot=inv_jie[i]*inv_jie[n-i]%mod *u%mod *mul(x-i,mod-2)%mod;
     55         if ((n-i)&1)
     56             tot=-tot;
     57         (sum+=tot*y[i])%=mod;
     58     }
     59     return (sum+mod)%mod;
     60 }
     61 
     62 int main()
     63 {
     64     ll t,m,i,p,q,vp,vq;
     65     jie[0]=1;
     66     maxv=mod-1;
     67     for (i=1;i<=maxv;i++)
     68         jie[i]=jie[i-1]*i%mod;
     69     inv_jie[maxv]=mul(jie[maxv],mod-2);
     70     for (i=maxv-1;i>=0;i--)
     71     {
     72         inv_jie[i]=inv_jie[i+1]*(i+1)%mod;
     73         ///1~9999991 inv
     74         inv_num[i+1]=inv_jie[i+1]*jie[i]%mod;
     75     }
     76 
     77     /**
     78     inv
     79     t*(n+2*m)
     80     6000000
     81     log(9999990) 25
     82     **/
     83 
     84 
     85     scanf("%lld",&t);
     86     while (t--)
     87     {
     88         scanf("%lld%lld",&n,&m);
     89         for (i=0;i<=n;i++)
     90             scanf("%lld",&y[i]);
     91         y[n+1]=cal(n+1);
     92         n++;
     93 
     94         ///sum 1~n
     95         for (i=1;i<=n;i++)
     96             (y[i]+=y[i-1])%=mod;
     97 
     98         while (m--)
     99         {
    100             scanf("%lld%lld",&p,&q);
    101             p--;
    102             vq=q<=n?y[q]:cal(q);
    103             vp=p<=n?y[p]:cal(p);
    104             printf("%lld
    ",(vq-vp+mod)%mod);///L>=1
    105         }
    106     }
    107 
    108     return 0;
    109 }
    110 /*
    111 1
    112 3 10
    113 0 1 4 9
    114 3 5
    115 1 5
    116 
    117 
    118 1
    119 3 10
    120 5 5 5 5
    121 1 5
    122 */

    求逆不进行初始化,超时

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=9999991;
     14 const int maxn=1e3+10;
     15 
     16 /**
     17 better way:
     18 多项式快速插值
     19 luogo5158
     20 **/
     21 
     22 ll y[maxn],jie[maxn],inv_jie[maxn],n;
     23 ll maxv=1e3;
     24 
     25 ll mul(ll a,ll b)
     26 {
     27     ll y=1;
     28     while (b)
     29     {
     30         if (b&1)
     31             y=y*a%mod;
     32         a=a*a%mod;
     33         b>>=1;
     34     }
     35     return y;
     36 }
     37 
     38 ll cal(ll x)
     39 {
     40     ll i,u,tot,sum=0;
     41     u=1;
     42     for (i=x;i>=x-n;i--)
     43         u=u*i%mod;
     44     for (i=0;i<=n;i++)
     45     {
     46         tot=inv_jie[i]*inv_jie[n-i]%mod *u%mod *mul(x-i,mod-2)%mod;
     47         if ((n-i)&1)
     48             tot=-tot;
     49         (sum+=tot*y[i])%=mod;
     50     }
     51     return (sum+mod)%mod;
     52 }
     53 
     54 int main()
     55 {
     56     ll t,m,i,p,q,vp,vq;
     57     ///can also calculate 1~9999991 inv
     58     jie[0]=1;
     59     for (i=1;i<=maxv;i++)
     60         jie[i]=jie[i-1]*i%mod;
     61     inv_jie[maxv]=mul(jie[maxv],mod-2);
     62     for (i=maxv-1;i>=0;i--)
     63         inv_jie[i]=inv_jie[i+1]*(i+1)%mod;
     64 
     65     scanf("%lld",&t);
     66     while (t--)
     67     {
     68         scanf("%lld%lld",&n,&m);
     69         for (i=0;i<=n;i++)
     70             scanf("%lld",&y[i]);
     71         y[n+1]=cal(n+1);
     72         n++;
     73 
     74         ///sum 1~n
     75         for (i=1;i<=n;i++)
     76             (y[i]+=y[i-1])%=mod;
     77 
     78         while (m--)
     79         {
     80             scanf("%lld%lld",&p,&q);
     81             p--;
     82             vq=q<=n?y[q]:cal(q);
     83             vp=p<=n?y[p]:cal(p);
     84             printf("%lld
    ",(vq-vp+mod)%mod);///L>=1
     85         }
     86     }
     87 
     88     return 0;
     89 }
     90 /*
     91 1
     92 3 10
     93 0 1 4 9
     94 3 5
     95 1 5
     96 
     97 
     98 1
     99 3 10
    100 5 5 5 5
    101 1 5
    102 */

    way2.

    牛顿插值多项式

    均差(差分形式)

    204ms

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=9999991;
     14 const int maxn=1e3+10;
     15 
     16 ll x[maxn][maxn],n;
     17 ll jie[maxn],jie_inv[maxn];
     18 ll maxv=1e3+5;
     19 
     20 ll cal(ll v)
     21 {
     22     ll sum=0,c=1,i;
     23     for (i=0;i<=n;i++)
     24     {
     25         (sum+=x[0][i]*c)%=mod;
     26         c=c*(v-i)%mod;
     27     }
     28     return sum;
     29 }
     30 
     31 
     32 ll mul(ll a,ll b)
     33 {
     34     ll y=1;
     35     while (b)
     36     {
     37         if (b&1)
     38             y=y*a%mod;
     39         a=a*a%mod;
     40         b>>=1;
     41     }
     42     return y;
     43 }
     44 
     45 int main()
     46 {
     47     ll t,m,i,j,k,u,v,v1,v2;
     48     scanf("%lld",&t);
     49     jie[0]=1;
     50     for (i=1;i<=maxv;i++)
     51         jie[i]=jie[i-1]*i%mod;
     52     jie_inv[maxv]=mul(jie[maxv],mod-2);
     53     for (i=maxv-1;i>=0;i--)
     54         jie_inv[i]=jie_inv[i+1]*(i+1)%mod;
     55     while (t--)
     56     {
     57         scanf("%lld%lld",&n,&m);
     58         for (i=0;i<=n;i++)
     59             scanf("%lld",&x[i][i]);
     60         for (i=1;i<=n;i++)
     61             for (k=i,j=0;k<=n;k++,j++)
     62                 x[j][k]=(x[j+1][k]-x[j][k-1])%mod;
     63         v=0;
     64         for (k=n;k>=0;k--)
     65             (v+=x[k][n])%=mod;
     66         n++;
     67         x[n][n]=v;
     68 
     69 
     70         for (i=1;i<=n;i++)
     71             x[i][i]+=x[i-1][i-1];
     72 
     73         for (i=1;i<=n;i++)
     74             for (k=i,j=0;k<=n;k++,j++)
     75                 x[j][k]=(x[j+1][k]-x[j][k-1])%mod;
     76         for (i=2;i<=n;i++)
     77             for (k=i,j=0;k<=n;k++,j++)
     78                 x[j][k]=x[j][k]*jie_inv[i]%mod;
     79 
     80         while (m--)
     81         {
     82             scanf("%lld%lld",&u,&v);
     83             u--;
     84             v1=v<=n?x[v][v]:cal(v);
     85             v2=u<=n?x[u][u]:cal(u);
     86             printf("%lld
    ",((v1-v2)%mod+mod)%mod);
     87         }
     88     }
     89     return 0;
     90 }
     91 /*
     92 1
     93 3 10
     94 0 1 4 9
     95 3 5
     96 1 5
     97 
     98 
     99 1
    100 3 10
    101 5 5 5 5
    102 1 5
    103 */

    way3.

    若干个n次函数的和(i=1,2,...)

    n+1次函数

    直接求出n+1次函数的系数,自然数求幂

    没试过,时间复杂度可能稍大,可能需要各种预处理。

    预处理

    伯努利数 https://blog.csdn.net/cj1064789374/article/details/85388995

    斯特林数 https://blog.csdn.net/lyd_7_29/article/details/75041818

    G. Winner

    那时想的是强连通

    若缩点后,形成链结构,则起点(一个强连通集合)中的所有的点为可以赢的点。

    这个方法是 from https://acm.ecnu.edu.cn/wiki/index.php?title=2019_ICPC_China_Nanchang_Invitational_Programming_Contest

    队友那时也是这个方法,666!

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e5+10;
     15 
     16 /*
     17 winners:
     18 the one(x) that can win the winner(except x)
     19 */
     20 
     21 struct node
     22 {
     23     int a[3],num;
     24 }f[3][maxn];
     25 
     26 bool use[maxn];
     27 
     28 int cmp0(node x,node y)
     29 {
     30     return x.a[0]<y.a[0];
     31 }
     32 
     33 int cmp1(node x,node y)
     34 {
     35     return x.a[1]<y.a[1];
     36 }
     37 
     38 int cmp2(node x,node y)
     39 {
     40     return x.a[2]<y.a[2];
     41 }
     42 
     43 int main()
     44 {
     45     int n,q,x[3],d[3],i,j;
     46     bool vis;
     47     scanf("%d%d",&n,&q);
     48 
     49     for (j=0;j<3;j++)
     50         for (i=1;i<=n;i++)
     51             scanf("%d",&f[0][i].a[j]);
     52     for (i=1;i<=n;i++)
     53     {
     54         f[0][i].num=i;
     55         f[1][i]=f[2][i]=f[0][i];
     56     }
     57 
     58     sort(f[0]+1,f[0]+n+1,cmp0);
     59     sort(f[1]+1,f[1]+n+1,cmp1);
     60     sort(f[2]+1,f[2]+n+1,cmp2);
     61 
     62     d[0]=d[1]=d[2]=n;
     63     x[0]=x[1]=x[2]=inf;
     64     ///f[0][0].a[0],f[1][0].a[1],f[2][0].a[2] init 0; Value > 0
     65     for (i=0;i<3;i++)
     66         if (f[i][n].a[i]>f[i][n-1].a[i])
     67         {
     68             use[f[i][n].num]=1;
     69             for (j=0;j<3;j++)
     70                 x[j]=min(x[j],f[i][n].a[j]);
     71         }
     72     while (1)
     73     {
     74         for (i=0;i<3;i++)
     75         {
     76             while (f[i][d[i]].a[i]>x[i])
     77             {
     78                 for (j=0;j<3;j++)
     79                     x[j]=min(x[j],f[i][d[i]].a[j]);
     80                 use[f[i][d[i]].num]=1;
     81                 d[i]--;
     82             }
     83         }
     84         vis=1;
     85         for (i=0;i<3;i++)
     86             if (f[i][d[i]].a[i]>x[i])
     87                 vis=0;
     88         if (vis)
     89             break;
     90     }
     91 
     92     while (q--)
     93     {
     94         scanf("%d",&i);
     95         printf("%s
    ",use[i]?"YES":"NO");
     96     }
     97     return 0;
     98 }
     99 /*
    100 n=1
    101 
    102 */

    H. Another Sequence

    遗憾场上没做出来。。。

    xor的题目

    要想到fwt啊!!!

    何况还是两个数组直接的操作

    之后就是动态开点线段树了,

    对于求根号,不会经历多少次,

    初始题目,没有说求根号向下取整,差评……

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxg=(1e5+10)*4;
     15 const int maxn=1e7;
     16 
     17 int n,id;
     18 ll a[maxg],b[maxg],cnt[maxg];
     19 int maxs;
     20 
     21 struct node
     22 {
     23     int l,r,g,tag;
     24 }f[maxn];
     25 
     26 ///log(1e10)*1e5
     27 
     28 void fwt(ll *a)
     29 {
     30     int cnt_pre,cnt_cur,i,j;
     31     for (cnt_pre=1,cnt_cur=2;cnt_pre<maxs;cnt_pre<<=1,cnt_cur<<=1)
     32         for (i=0;i<maxs;i+=cnt_cur)
     33             for (j=0;j<cnt_pre;j++)
     34                 a[i+j+cnt_pre]+=a[i+j];
     35 }
     36 
     37 void ufwt(ll *a)
     38 {
     39     int cnt_pre,cnt_cur,i,j;
     40     for (cnt_pre=1,cnt_cur=2;cnt_pre<maxs;cnt_pre<<=1,cnt_cur<<=1)
     41         for (i=0;i<maxs;i+=cnt_cur)
     42             for (j=0;j<cnt_pre;j++)
     43                 a[i+j+cnt_pre]-=a[i+j];
     44 }
     45 
     46 void push_down(int ind)
     47 {
     48     f[f[ind].l].g+=f[ind].tag;
     49     f[f[ind].r].g+=f[ind].tag;
     50     f[f[ind].l].tag+=f[ind].tag;
     51     f[f[ind].r].tag+=f[ind].tag;
     52     f[ind].tag=0;
     53 }
     54 
     55 void update(int ind,ll l,ll r,int x,int y)
     56 {
     57     if (x<=l && r<=y)
     58     {
     59         f[ind].g++;
     60         f[ind].tag++;   ///用于传给子节点的
     61         return;
     62     }
     63     if (!f[ind].l)
     64         f[ind].l=++id;
     65     if (!f[ind].r)
     66         f[ind].r=++id;
     67     if (f[ind].tag)
     68         push_down(ind);
     69     int m=(l+r)>>1;
     70     if (x<=m)
     71         update(f[ind].l,l,m,x,y);
     72     if (m<y)
     73         update(f[ind].r,m+1,r,x,y);
     74 }
     75 
     76 int query(int ind,ll l,ll r,int x)
     77 {
     78     if (l==r)
     79         return f[ind].g;
     80     if (!f[ind].l)
     81         f[ind].l=++id;
     82     if (!f[ind].r)
     83         f[ind].r=++id;
     84     if (f[ind].tag)
     85         push_down(ind);
     86     int m=(l+r)>>1;
     87     if (x<=m)
     88         return query(f[ind].l,l,m,x);
     89     return query(f[ind].r,m+1,r,x);
     90 }
     91 
     92 int main()
     93 {
     94     int q,i,j,ci;
     95     ll x,y,num,nn;
     96     int maxv=2e5;
     97     scanf("%d",&n);
     98     for (i=0;i<n;i++)
     99     {
    100         scanf("%d",&j);
    101         a[j]++;
    102     }
    103     for (i=0;i<n;i++)
    104     {
    105         scanf("%d",&j);
    106         b[j]++;
    107     }
    108 
    109     maxs=1;
    110     ///1e5*2 maxvalue
    111     while (maxs<1e5*2)
    112         maxs<<=1;
    113 
    114     ///(5*10^4)^2
    115     fwt(a);
    116     fwt(b);
    117     for (i=0;i<maxs;i++)
    118         a[i]=a[i]*b[i];
    119     ufwt(a);
    120     cnt[0]=a[0];
    121     for (i=1;i<=maxv;i++)
    122         cnt[i]=cnt[i-1]+a[i];
    123 
    124     id=1;///对应query(1,...)
    125     nn=n*n;
    126     scanf("%d",&q);
    127     while (q--)
    128     {
    129         scanf("%lld%lld",&x,&y);
    130         if (x==0)
    131         {
    132             ci=query(1,1,nn,y);
    133             num=lower_bound(cnt,cnt+maxv,y)-cnt;
    134             while (ci-- && num!=1)
    135                 num=sqrt(num);
    136             printf("%lld
    ",num);
    137         }
    138         else
    139             update(1,1,nn,x,y);
    140     }
    141     return 0;
    142 }
    143 /*
    144 3 3 5 5 7 7 7 7 7 7 7 7 7 7 7 10 11 13 13 14 14 14 15 15 15
    145 */

    验证程序

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10 
    11 const double eps=1e-8;
    12 const ll inf=1e9;
    13 const ll mod=1e9+7;
    14 const int maxn=1e5+10;
    15 
    16 int a[maxn],b[maxn],c[maxn];
    17 
    18 int main()
    19 {
    20     int n,i,j;
    21     scanf("%d",&n);
    22     for (i=0;i<n;i++)
    23         scanf("%d",&a[i]);
    24     for (i=0;i<n;i++)
    25         scanf("%d",&b[i]);
    26     for (i=0;i<n;i++)
    27         for (j=0;j<n;j++)
    28             c[a[i]|b[j]]++;
    29     for (i=0;i<=30;i++)
    30     {
    31         while (c[i]--)
    32             printf("%d ",i);
    33     }
    34     return 0;
    35 }
    36 /*
    37 5
    38 6 2 6 4 5
    39 1 7 9 10 3
    40 3 3 5 5 7 7 7 7 7 7 7 7 7 7 7 10 11 13 13 14 14 14 15 15 15
    41 */
  • 相关阅读:
    Consul常用命令
    ECharts 避免变窄
    TP3.2 日期默认格式
    新订单提示效果
    php 按照字典序排序 微信卡券签名算法用到
    td宽度自适应 窄的地方自动收缩
    git 删除本地分支,删除远程分支
    分页Model
    chrome表单自动填充如何取消
    tp3.2 如何比较两个字段
  • 原文地址:https://www.cnblogs.com/cmyg/p/11255754.html
Copyright © 2020-2023  润新知