zoukankan      html  css  js  c++  java
  • [考试反思]0520省选模拟101:目的

    没得说。怎么这么菜啊。

    $T1$的$60$分白送的基本都不用想。

    (诶那我这场考试干啥了?

    $T2$看着像个$min25$筛的板子。就是数据范围大了点

    然而因为几乎没怎么遇到过$min25$的题,只写过一次而且还是三个月前了。

    所以基本上是忘的一干二净考场上一点一点尝试想的。

    结果写的混天黑地终于写完,过掉样例,就交了。

    十分快乐的是:少取了个模。直接爆零。然后这场就没了。

    就当是练习不熟练的知识点了(自己都不信。。。

    我到现在都不知道我这么做的目的是什么。但愿不要再考场弱智了(事实上明天还是这样

    T1:石子游戏

    大意:$nim$。问去掉最少几堆石子后可以先手必胜。$n le 5 imes 10^5,A le 5 imes 10^5$

    要求出最少用多少个堆能得到和所有石子堆一样的异或值。

    删掉的石子堆数是$logA$级别。否则线性基可以表出就可以去掉了。

    所以暴力做$dp$是$O(n^2)$的。每一轮用$xorFWT$优化可以做到$O(nlog^2n)$。用$FWT$本质求单点点值可以做到$O(nlogn)$

     1 #include<cstdio>
     2 #define S 1<<19
     3 int a[S],n,t[S],T,ans;
     4 void FWT(int*a){for(int i=1;i<S;i<<=1)for(int j=0;j<S;j+=i<<1)for(int k=j,x,y;k<j+i;++k)x=a[k],y=a[k+i],a[k]=x+y,a[k+i]=x-y;}
     5 int main(){
     6     scanf("%d",&n);n++;
     7     for(int i=1,x;i<n;++i)scanf("%d",&x),T^=x,t[x]=1;
     8     a[T]=1; FWT(t);
     9     while(n--,!a[0]){FWT(a);for(int i=0;i<S;++i)a[i]=a[i]*t[i];FWT(a);for(int i=0;i<S;++i)a[i]=a[i]?1:0;}
    10     printf("%d
    ",n);
    11 }
    View Code

    T2:函数

    大意:$f(p^e)=p^k,f(ab)=f(a)f(b)((a,b)=1)$。求$sumlimits_{i=1}^{n} f(i)$。$n le 10^{13},k le 20$

    送上$min25$模板。

     1 #include<cstdio>
     2 #include<cmath>
     3 #define ll long long
     4 #define mod 1000000007
     5 const int S=12345678,s=3333333;
     6 ll n,v[S];int k,iv[23],st[23][23],g0[s],g1[s],p[S],pc,vc,sq,f[s],pre[s]; bool np[S];
     7 int&g(ll x){return x<=sq?g0[x]:g1[n/x];}
     8 int mo(int x){return x>=mod?x-mod:x;}
     9 int spw(ll n,int k,int a=0){n%=mod;for(int i=0,C=n+1;i<=k;++i)a=(a+1ll*st[k][i]*C%mod*iv[i+1])%mod,C=C*1ll*(n-i)%mod;return a;}
    10 int pw(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
    11 int Sum(ll n,int c,int a=0){
    12     if(p[c]>n||n<=1)return 0;
    13     for(int z=c;z<=pc&&1ll*p[z]*p[z]<=n;++z)
    14         for(ll t=p[z];1ll*t*p[z]<=n;t*=p[z])a=(a+f[p[z]]*(1ll+Sum(n/t,z+1)))%mod;
    15     return mo(a+mo(g(n)-pre[c-1]+mod));
    16 }
    17 int main(){
    18     scanf("%lld%d",&n,&k);
    19     st[0][0]=iv[1]=1; sq=sqrt(n);
    20     for(int i=1;i<=k;++i)for(int j=1;j<=i;++j)st[i][j]=(st[i-1][j]*1ll*j+st[i-1][j-1])%mod;
    21     for(int i=2;i<23;++i)iv[i]=mod-mod/i*1ll*iv[mod%i]%mod;
    22     
    23     f[1]=pre[0]=1;
    24     for(int i=2;i<=sq;++i){
    25         if(!np[i])p[++pc]=i,f[i]=pw(i,k),pre[pc]=mo(pre[pc-1]+f[i]);
    26         for(int j=1,x;(x=i*p[j])<=sq;++j){
    27             np[x]=1; f[x]=f[i]*f[p[j]];
    28             if(i%p[j]==0){f[x]=f[i];break;}
    29         }
    30     }
    31     for(ll i=1,r,N;N=n/i,i<=n;i=r+1)r=n/N,v[++vc]=N;
    32     for(int i=1;i<=vc;++i)g(v[i])=spw(v[i],k)-(!k);
    33     for(int i=1;i<=pc;++i)for(int j=1;1ll*p[i]*p[i]<=v[j];++j)g(v[j])=(g(v[j])-1ll*(g(v[j]/p[i])-pre[i-1])*f[p[i]]%mod+mod)%mod;
    34     printf("%d
    ",mo(Sum(n,1)+1+mod));
    35 }
    View Code

    我们构造一个$g(x)=x^k$。再尝试设计一个$h$使得$f=g*h$。是狄利克雷卷积。

    $f(1)=g(1)h(1)$。所以有$h(1)=1$

    $f(p)=g(p)h(1)+h(p)g(1)$。所以有$h(p)=0$

    继续搞下去,还有$h(p^e)=p^e-p^{2e}$。当然$h$也是积性函数。

    那么我们就知道$h$只在$powerful number$处有值。

    设$G(n)=sumlimits_{i=1}^{n} g(i)$。是个自然数幂和可以$O(k)$算

    $sumlimits_{i=1}^{n} f(i) =sumlimits_{j=1}^{n} sumlimits_{d|i}g(d)h(frac{n}{i})$

    $=sumlimits_{i=1}^{n} h(i) sumlimits_{j=1}^{frac{n}{i}} j$

    $=sumlimits_{i=1}^{n} h(i) G(frac{n}{i})$

    爆搜出所有的$powerful number$(每次搜索必定找到一个,总共的数量是$sqrt{n}$级别)。对于每个$powerful number$计算一个对应的$G$也就是自然数幂和

    复杂度$O(ksqrt{n})$。可能有点卡常,自然数幂和可以记忆化。

     1 #include<cstdio>
     2 #include<cmath>
     3 #define ll long long
     4 const int S=10000007,mod=1000000007;
     5 ll n;int k,iv[23],st[23][23],p[S],pc,sq,h[S]; bool np[S];
     6 int spw(int n,int a=0){for(int i=0,C=n+1;i<=k;++i)a=(a+1ll*st[k][i]*C%mod*iv[i+1])%mod,C=C*1ll*(n-i)%mod;return a;}
     7 int pw(int b,int t=k,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     8 struct hash_map{
     9     int fir[S],l[S],v[S],ec;ll to[S];
    10     int&operator[](ll x){int r=x%S;
    11         for(int i=fir[r];i;i=l[i])if(to[i]==x)return v[i];
    12         l[++ec]=fir[r];fir[r]=ec;to[ec]=x;return v[ec]=spw(x%mod);
    13     }
    14 }M;
    15 int Sum(ll n,int hp,int c,int a=0){
    16     for(int z=c;z<=pc;++z){
    17         ll t=n/p[z]/p[z]; if(!t)break; int Hp=hp*1ll*h[p[z]]%mod;
    18         for(;t;t/=p[z])a=(a+Sum(t,Hp,z+1))%mod;
    19     }return (a+1ll*hp*M[n])%mod;
    20 }
    21 int main(){
    22     scanf("%lld%d",&n,&k);
    23     st[0][0]=iv[1]=1; sq=sqrt(n);
    24     for(int i=1;i<=k;++i)for(int j=1;j<=i;++j)st[i][j]=(st[i-1][j]*1ll*j+st[i-1][j-1])%mod;
    25     for(int i=2;i<23;++i)iv[i]=mod-mod/i*1ll*iv[mod%i]%mod;
    26     for(int i=2;i<=sq;++i){
    27         if(!np[i])p[++pc]=i,h[i]=pw(i)-pw(1ll*i*i%mod),h[i]+=h[i]<0?mod:0;
    28         for(int j=1,x;(x=i*p[j])<=sq;++j){np[x]=1;if(i%p[j]==0)break;}
    29     }printf("%d",Sum(n,1,1));
    30 }
    View Code

    T3:画

    大意:图,每个点$i$的权值在$[0,limit_i]$。有边相邻的两个点权值不同。所有点异或和为给定值$C$。$n le 15,limit,C le 10^{18}$

    先考虑没有边。那感觉上就是一个数位$dp$了。

    我们逐位考虑,并且强制目前考虑位的更高位上所有数都紧贴上界(如果贴到上界和$C$的高位不符则直接跳出)

    设$dp[i][0/1][0/1]$表示考虑了前$i$个数,是否有数脱离上界,当前考虑位上是$1$还是$0$。

    这个可以简单转移。$dp[n][1][bit(C,x)]$就是答案。复杂度是$O(n imes logC)$

    然后考虑边数很少的情况。不难想到容斥,状压枚举那些边符合条件。子集反演得到容斥系数就是$-1$的边集的大小次幂。

    考虑优化,在刚才这种想法里有一些冗余状态,例如说$1-2,2-3$相同而$1-3$不同。这显然是非法的。

    所以我们枚举一个点集,点集的系数是:在当前点集所有联通导出子图的容斥系数之和。

    也就是每次强制一个点集同色,不同点集不限制来进行计算。

    这个系数可以用全集减非法得到。每次枚举$1$号点所在连通块。由于正负组合数和为$0$,所以可以知道所有存在边的子集的所有导出子图(不一定联通)的容斥系数和为$0$否则为$1$。

    这样就很好转移了。设$dp[i][j]$表示当前已选点集是$i$,全局所有点的异或和相当于$j$集合所有点的异或和。

    考虑怎么得到$j$:如果一个连通块大小是偶数,那么为全局异或和贡献是$0$。如果是奇数,那么取决于$limit$最小的点。

    我们知道$j$一定是$i$的子集。状态数是$n^3$的。转移时钦定最小点必须被包含,枚举补集的子集。

    因为有对于当前点集$j$中$limit$最大的点,它右侧一定不存在$2$。这样是$sum 3^i 2^{n-i}$。积分出来还是$3^n$。所以复杂度是对的。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define ll long long
     4 #define mod 998244353
     5 #define S 1<<15
     6 int n,m,ie[S],ans,c[S],bit[S],pw[S],t23[S],dp[55555555],mnp[S]; ll a[16],C;
     7 void mo(int&x){if(x>=mod)x-=mod;}
     8 int&T(int s,int t){return dp[t23[s]+t23[t]];}
     9 #define any (1ll<<i)
    10 #define lim ((a[j]&any-1)+1)
    11 int ask(int s,int A=0){
    12     static int dp[16][2][2];dp[0][0][0]=1;
    13     for(int i=59,c;c=0,~i;--i){
    14         for(int j=1;j<=n;++j){
    15             if(s>>j-1&1^1){for(int x=0;x<2;++x)for(int y=0;y<2;++y)dp[j][x][y]=dp[j-1][x][y];continue;}
    16             dp[j][0][0]=dp[j][0][1]=dp[j][1][0]=dp[j][1][1]=0;
    17             for(int x=0;x<2;++x)for(int y=0;y<2;++y)
    18                 if(a[j]>>i&1)mo(dp[j][1][y]+=dp[j-1][x][y]*(x?any%mod:1)%mod),mo(dp[j][x][y^1]+=dp[j-1][x][y]*(lim%mod)%mod);
    19                 else mo(dp[j][x][y]+=dp[j-1][x][y]*(lim%mod)%mod);
    20             c^=a[j]>>i&1;
    21         }mo(A+=dp[n][1][C>>i&1]); if(C>>i&1^c)break;else A+=!i;
    22     }return A;
    23 }
    24 int main(){
    25     scanf("%d%d%lld",&n,&m,&C); a[0]=2e18;
    26     for(int i=1;i<=n;++i)scanf("%lld",&a[i]),mnp[1<<i-1]=i;
    27     for(int i=1,x,y;i<=m;++i){
    28         scanf("%d%d",&x,&y);
    29         for(int j=0;j<1<<n;++j)if(j&1<<x-1&&j&1<<y-1)ie[j]=1;
    30     }
    31     for(int i=1;i<1<<n;++i)bit[i]=bit[i^i&-i]^1,mnp[i]=i^i&-i?(mnp[i&-i^(a[mnp[i^i&-i]]<a[mnp[i&-i]]?i:0)]):mnp[i];
    32     for(int i=pw[0]=1;i<n;++i)pw[i]=pw[i-1]*3;
    33     for(int i=0;i<1<<n;++i)for(int j=0;j<n;++j)if(i>>j&1)t23[i]+=pw[j];
    34     for(int i=1;i<1<<n;++i){
    35         int x=i&-i;c[i]=!ie[i];
    36         for(int j=i-1&i;j;j=j-1&i)if(j&x&&!ie[i^j])mo(c[i]+=mod-c[j]);
    37     }
    38     dp[0]=1; int U=(1<<n)-1; 
    39     for(int i=0;i<=U;++i)for(int j=i,l=!j;l<2;j=j-1&i,l+=l+!j)if(T(i,j))for(int e=U^i,r=e;r;r=r-1&e)if((e&-e)==(r&-r))
    40         if(bit[r])mo(T(i|r,j|1<<mnp[r]-1)+=1ll*T(i,j)*c[r]%mod);
    41         else mo(T(i|r,j)+=1ll*T(i,j)*c[r]%mod*((a[mnp[r]]+1)%mod)%mod);
    42     for(int i=0;i<1<<n;++i)if(T(U,i))mo(ans+=1ll*ask(i)*T(U,i)%mod);
    43     printf("%d",ans);
    44 }
    View Code
  • 相关阅读:
    QR code
    复制一个带random指针的链表
    运行时const
    海量处理 bitmap及区段划分
    socket编程随记
    BLS签名
    load balancing
    Bloom Filter (2)
    #include 的花样
    拓扑排序、Dijkstra、Prim/Kruskal、全部最短路径/传递闭包
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12934133.html
Copyright © 2011-2022 走看看