• [考试反思]0403省选模拟61:快乐


    开心的像个孩子。

    $T2$神赐的数据,乱搞能拿到$80$。(其实再加两条特判就能$AC$

    $T1$是$dy$原题。总算没有翻车。

    $T2$的话,我研究了一会,没什么思路于是开始乱搞。

    于是直接输出答案的上界,结果过了大样例,就交了。

    $T3$的话,题目描述有误+自己没看清题,写了个$15pts$的暴力结果爆零了。

    赶巧小样例答案是无解大样例又太大,完全没意识到自己读错理解错。

    其实思路已经有了,但是看错题之后就完全不可做了,白瞎我想了半天。

    T1:GTM

    https://www.cnblogs.com/hzoi-DeepinC/protected/p/12323822.html

    (Code:4)第8题。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 200005
     4 #define mod 66662333
     5 struct pt{int x,v;friend bool operator<(pt a,pt b){return a.v<b.v;}}P[S];
     6 struct sg{int l,r;friend bool operator<(sg a,sg b){return a.l<b.l||(a.l==b.l&&a.r<b.r);}}L[S];
     7 int n,t[S],cnt; map<int,int>M;
     8 int mo(int x){return x>=mod?x-mod:x;}
     9 void Add(int p,int v){for(;p<=n+1;p+=p&-p)t[p]=min(t[p],v);}
    10 int Ask(int p,int a=n){for(;p;p^=p&-p)a=min(a,t[p]);return a;}
    11 void ADD(int p,int v){for(;p<=n+1;p+=p&-p)t[p]=max(t[p],v);}
    12 int ASK(int p,int a=1){for(;p;p^=p&-p)a=max(a,t[p]);return a;}
    13 void add(int p,int v){for(;p<=n+1;p+=p&-p)t[p]=mo(t[p]+v);}
    14 int ask(int p,int a=0){for(;p;p^=p&-p)a=mo(a+t[p]);return a;}
    15 int main(){
    16     cin>>n;
    17     for(int i=1;i<=n;++i)scanf("%d%d",&P[i].x,&P[i].v),t[i]=P[i].x;
    18     sort(P+1,P+1+n); sort(t+1,t+1+n);
    19     for(int i=1;i<=n;++i)M[t[i]]=i,t[i]=n;
    20     for(int i=1;i<=n;++i)Add(n+1-M[P[i].x],i),L[i].l=Ask(n+1-M[P[i].x]);
    21     for(int i=1;i<=n;++i)t[i]=1;
    22     for(int i=n;i;--i)ADD(M[P[i].x],i),L[i].r=ASK(M[P[i].x]);
    23     for(int i=1;i<=n;++i)t[i]=0;
    24     sort(L+1,L+1+n); t[n+1]=1;
    25     for(int i=1;i<=n;++i)add(n+1-L[i].r,ask(n+2-L[i].l));
    26     cout<<t[1]<<endl;
    27 }
    我才知道树状数组可以倒着写,然而并没有写

    T2:字符串游戏

    大意:给定字符串。$S_0,T$。第$i$轮操作可以使$S_{i,j}$成为$S_{i,j-1}$或$S_{i-1,j}$。求最少多少次操作能使$S=T$。$nle 10^6$

    我们依次把$S_0,S_1...S_x$列出来。发现操作就是,从$T$出发,每次只能往上或往左走,最后要走到$S$中的相同字符,路径可以合并不可交叉,要求行数尽量少。

    贪心而言,越晚转弯越好。我们对于每个$T$的极长相同段,找到更靠前的$S$的第一次出现,这段区间就都是被横着走所覆盖的。

    我们只需要知道对于每个位置,有多少个不重叠的横着走的,答案对此取$max$即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int ans,n;char t[1000005],s[1000005];
     4 int main(){
     5     scanf("%d%s%s",&n,s+1,t+1);
     6     for(int i=1;i<=n;++i)if(s[i]!=t[i])goto x;
     7     return puts("0"),0;x:
     8     for(int i=n;i>0;--i){
     9         int f=0,sp=i,tp;
    10         re:f++;tp=i;
    11         while(sp&&s[sp]!=t[i])sp--;
    12         while(tp>=sp&&t[tp]==t[i])tp--;tp++;
    13         if(!sp)return puts("-1"),0;
    14         i=tp-1;
    15         if(sp==tp)ans=max(ans,f);
    16         else goto re;
    17     }cout<<ans<<endl;
    18 }
    View Code

    T3:ACE

    大意:一个$k$点$m$边的无向图,将这个图复制成$n$份。对于新的$nk$个点的图的补图,问有多少种哈密顿路径(不是回路)。$k le 14,n le 50000$

    题目其实也就是在说,不能经过原图里的任何边。

    这个我们不会求,于是我们求它经过了多少补图的边。

    对于任意一条哈密顿路径,我们考虑,每两条补图边之间,一定是一条「在其中一份原图的路径」(单独一个点也视为一条路径)

    那么我们可以得知:补图边数=原图路径数-1

    然后我们就可以据此求出所有哈密顿路径的原图路径数(直接求不好求,我们可以利用“至少”,也就是说,两个原图路径之间,可能也是原图路径)

    通过容斥得到补图边数恰好$=n*k-1$的总方案数。

    接下来在原图上,对于

    首先通过简单$dp$可以得到$f[s]$表示用原图的一条路径经过点集$s$的方案数

    然后做一个背包$dp$得到$dp[i]$表示用$i$条原图路径恰好覆盖满所有点的方案数(顺序不同计做不同方案)

    我们对$dp$做一个指数型生成函数就完事了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 998244353
     4 int mo(int x){return x>=mod?x-mod:x;}
     5 int n,k,m,mp[15][15],dp[1<<15][15],f[1<<15],g[15][1<<15],ans,len,rev[1<<21],A[1<<21],fac[1<<21],finv[1<<21];
     6 int qp(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;}
     7 void sat(int l){
     8     len=1;while(len<=l)len<<=1;
     9     for(int i=1;i<len;++i)rev[i]=rev[i>>1]>>1|(i&1?len>>1:0);
    10 }
    11 void NTT(int*a,int op){
    12     for(int i=1;i<len;++i)if(rev[i]>i)swap(a[i],a[rev[i]]);
    13     for(int i=1;i<len;i<<=1)for(int j=0,w=qp(3,(mod-1)/2/i*op+mod-1);j<len;j+=i<<1)
    14         for(int k=j,t=1,x,y;k<j+i;++k,t=1ll*t*w%mod)
    15             x=a[k],y=1ll*a[k+i]*t%mod,a[k]=mo(x+y),a[k+i]=mo(x-y+mod);
    16     if(op==-1)for(int i=0,iv=qp(len,mod-2);i<len;++i)a[i]=1ll*a[i]*iv%mod;
    17 }
    18 int main(){//freopen("wings.in","r",stdin);
    19     cin>>n>>k>>m;
    20     for(int i=1,a,b;i<=m;++i)scanf("%d%d",&a,&b),mp[a][b]=mp[b][a]=1;
    21     const int mst=(1<<k)-1;
    22     for(int s=1;s<=k;++s)dp[1<<s-1][s]=1;
    23     for(int x=1;x<=mst;++x)for(int t=1;t<=k;++t)if(dp[x][t]){
    24         for(int j=1;j<=k;++j)if(mp[t][j]&&!(x&1<<j-1))dp[x|1<<j-1][j]=mo(dp[x|1<<j-1][j]+dp[x][t]);
    25         f[x]=mo(f[x]+dp[x][t]);
    26     }
    27     g[0][0]=1;// for(int i=1;i<=mst;++i)cerr<<f[i]<<endl;
    28     for(int i=1;i<=k;++i)for(int s=1;s<=mst;++s)for(int e=s;e;e=e-1&s)g[i][s]=(g[i][s]+1ll*g[i-1][s^e]*f[e])%mod;
    29     sat(n*k);
    30     for(int i=fac[0]=1;i<=n*k;++i)fac[i]=1ll*fac[i-1]*i%mod;
    31     finv[n*k]=qp(fac[n*k],mod-2);
    32     for(int i=n*k-1;~i;--i)finv[i]=finv[i+1]*(i+1ll)%mod;
    33     for(int i=1;i<=k;++i)A[i]=g[i][mst]*1ll*finv[i]%mod;
    34     NTT(A,1);
    35     for(int i=0;i<len;++i)A[i]=qp(A[i],n);
    36     NTT(A,-1);
    37     for(int i=1;i<=n*k;++i)ans=(ans+1ll*fac[i]*(n*k-i&1?mod-A[i]:A[i]))%mod;
    38     cout<<ans<<endl;
    39 }
    View Code
  • 相关阅读:
    JavaScript入门基础(三)
    JavaScript入门基础(二)
    Web页面该如何布局
    如何通过SQL创建删除表的索引,UNIQUE KEY
    vim使用大全
    安装vmwaretools后 真机和虚拟机仍不能复制黏贴
    php通用函数html时间文件大小生成随机数
    Centos下安装配置phpmyadmin
    [Leetcode 43] 11 Container With Most Water
    [Leetcode 39] 129 Sum Root to Leaf Numbers
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12628977.html
Copyright © 2020-2023  润新知