zoukankan      html  css  js  c++  java
  • 4.12上午 模拟赛

    T1 bzoj 2806

    题目大意:

    给出$n$个字符串表示模式串,$m$次询问,每次给出一个串

    对于一个模式串的子串,我们可以将其称为一个好的串

    对于一个给出的串,需要将这个串划分为若干段,使得这些段中好的串的总长度不少于总长的$85%$

    现在要使这个划分方案中最短的好的串的长度最大,输出这个满足条件的情况下最短串长度的最大值

    思路:

    很容易想到二分答案,得到$f_i=max(f_j+i-j),j<=i-mid$其中$s[j:i]$为一个加分句

    用广义后缀自动机处理出每个点向前最远可以匹配到的位置

    这个位置是单调上升的,用单调队列维护一个dp值单调下降的队列即可

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define db double
     4 #define inf 2139062143
     5 #define MAXN 2001000
     6 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
     7 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
     8 #define ren for(register int i=fst[x];i;i=nxt[i])
     9 #define pls(a,b) (a+b)%MOD
    10 #define mns(a,b) (a-b+MOD)%MOD
    11 #define mul(a,b) (1LL*(a)*(b))%MOD
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+(ch&15);ch=getchar();}
    18     return x*f;
    19 }
    20 int n,m,mxl[MAXN],pos[MAXN],fa[MAXN],tr[MAXN][2],las=1,tot=1;
    21 int len,f[MAXN],q[MAXN],hd,tl;
    22 char s[MAXN];
    23 void extend(int c)
    24 {
    25     int p=las,np=las=++tot;mxl[np]=mxl[p]+1;
    26     for(;p&&!tr[p][c];p=fa[p]) tr[p][c]=np;
    27     if(!p) {fa[np]=1;return ;}int q=tr[p][c];
    28     if(mxl[q]==mxl[p]+1) {fa[np]=q;return ;}
    29     int nq=++tot;mxl[nq]=mxl[p]+1;
    30     memcpy(tr[nq],tr[q],sizeof(tr[nq]));
    31     fa[nq]=fa[q],fa[q]=fa[np]=nq;
    32     for(;p&&tr[p][c]==q;p=fa[p]) tr[p][c]=nq;
    33 }
    34 int X(int x) {return f[x]-x;}
    35 int cheq(int x)
    36 {
    37     hd=1,tl=0;rep(i,1,len)
    38     {
    39         f[i]=f[i-1];if(i<x) continue;
    40         while(hd<=tl&&X(q[tl])<=X(i-x)) tl--;q[++tl]=i-x;
    41         while(hd<=tl&&q[hd]<i-pos[i]) hd++;
    42         if(hd<=tl) f[i]=max(f[i],f[q[hd]]+i-q[hd]);
    43     }
    44     return f[len]*20>=len*17;
    45 }
    46 int main()
    47 {
    48     n=read(),m=read();rep(i,1,m)
    49     {
    50         scanf("%s",s+1);len=strlen(s+1);
    51         las=1;rep(i,1,len) extend(s[i]-'a');
    52     }
    53     int p,c,res,l,r,mid,ans;rep(i,1,n)
    54     {
    55         scanf("%s",s+1);len=strlen(s+1),p=1,res=0;
    56         rep(i,1,len)
    57         {
    58             c=s[i]-'a';if(tr[p][c]) {pos[i]=++res,p=tr[p][c];continue;}
    59             for(;p&&!tr[p][c];p=fa[p]);
    60             if(!p) pos[i]=res=0,p=1;else pos[i]=res=mxl[p]+1,p=tr[p][c];
    61         }
    62         for(l=ans=0,r=len;mid=l+r>>1,l<=r;)
    63             if(cheq(mid)) ans=mid,l=mid+1;else r=mid-1;
    64         printf("%d
    ",ans);
    65     }
    66 }
    View Code

    T2 bzoj 4657

    题目大意:

    一个网格图,有一些发射点可以发射单向的射线,保证不会有发射点在别的点的线上,除了发射点每个点有一个权值

    每个发射点可以在射线上取一个点,拿到这个点的权值,需要在保证这些发射点与选的点不相交的情况下,使取的点权值和最大

    思路:

    先假设每个发射点都取到了它能取到的最大值

    使用最小割来满足不相交的条件,因为每个点最多被两个分别为横竖的发射点所覆盖

    每个点拆成两个点,其中一个向另一个连$inf$的边表示不能被割

    每个点发射出去的射线连成一条链,每个边的权值是最大值-这个点的权值,表示割边=选这个点

    然后用总答案去减即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #define ll long long
    12 #define db double
    13 #define inf 2139062143
    14 #define MAXN 5010
    15 #define MAXM 20100
    16 #define MOD 998244353
    17 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
    18 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
    19 #define ren for(register int i=fst[x];i;i=nxt[i])
    20 #define pls(a,b) (a+b)%MOD
    21 #define mns(a,b) (a-b+MOD)%MOD
    22 #define mul(a,b) (1LL*(a)*(b))%MOD
    23 using namespace std;
    24 inline int read()
    25 {
    26     int x=0,f=1;char ch=getchar();
    27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    28     while(isdigit(ch)) {x=x*10+(ch&15);ch=getchar();}
    29     return x*f;
    30 }
    31 int n,m,mp[55][55],dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    32 struct Dinic
    33 {
    34     int fst[MAXN],nxt[MAXM<<1],to[MAXM<<1],cnt,val[MAXM<<1];
    35     int vis[MAXN],q[MAXN],l,r,S,T,tot,dis[MAXN],cur[MAXN];
    36     Dinic(){memset(fst,0,sizeof(fst));cnt=1,tot=0;}
    37     void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
    38     void ins(int u,int v,int w) {add(u,v,w);add(v,u,0);}
    39     int bfs()
    40     {
    41         vis[T]=++tot,dis[T]=0,q[l=r=1]=T;int x;
    42         while(l<=r)
    43         {
    44             x=q[l++],cur[x]=fst[x];ren if(val[i^1]&&vis[to[i]]!=tot)
    45                 dis[to[i]]=dis[x]+1,vis[to[i]]=tot,q[++r]=to[i];
    46         }
    47         return vis[S]==tot;
    48     }
    49     int dfs(int x,int a)
    50     {
    51         if(x==T||!a) return a;int flw=0,f;
    52         for(int& i=cur[x];i&&a;i=nxt[i])
    53             if(val[i]&&dis[to[i]]==dis[x]-1&&(f=dfs(to[i],min(a,val[i]))))
    54                 val[i]-=f,val[i^1]+=f,a-=f,flw+=f;
    55         return flw;
    56     }
    57     int solve(int ss,int tt,int res=0)
    58         {S=ss,T=tt;while(bfs()) res+=dfs(S,inf);return res;}
    59 }D;
    60 int t(int x,int y,int w) {return (x-1)*m+y-1+w*n*m;}
    61 int ok(int x,int y) {return x&&y&&x<=n&&y<=m;}
    62 #define nx tx+dx[k]
    63 #define ny ty+dy[k]
    64 int main()
    65 {
    66     n=read(),m=read();int ss=2*n*m+1,tt=ss+1,k,tx,ty,mx,sum=0,tag;
    67     rep(i,1,n) rep(j,1,m) mp[i][j]=read();
    68     rep(i,1,n) rep(j,1,m) if(mp[i][j]>=0) D.ins(t(i,j,0),t(i,j,1),inf);
    69         else 
    70         {
    71             (tag=(mp[i][j]>=-2))?D.ins(ss,t(i,j,0),inf):D.ins(t(i,j,1),tt,inf);
    72             for(k=4+mp[i][j],mx=0,tx=i,ty=j;tx=nx,ty=ny,ok(tx,ty);)
    73                 mx=max(mx,mp[tx][ty]);sum+=mx;
    74             for(k=4+mp[i][j],tx=i,ty=j;ok(nx,ny);tx=nx,ty=ny)
    75                 if(tag) D.ins(t(tx,ty,0),t(nx,ny,0),mx-max(mp[tx][ty],0));
    76                 else D.ins(t(nx,ny,1),t(tx,ty,1),mx-max(mp[tx][ty],0));
    77         }
    78     printf("%d
    ",sum-D.solve(ss,tt));
    79 }
    View Code

    T3 Codeforces 960G

    题目大意:

    给出$n,a,b$ 问$n$的排列中,前缀最大值有$a$种,后缀最大值有$b$种的排列有多少个

    思路:

    很明显$n$这个数成为一个分界点

    对于前面的数, 每个最大值到下一个最大值之前的这段区间可以看做是一个环,把最大的数放在了第一个,后面同理

    这样相当于第一类斯特林数,将$n-1$个数分成$a+b-2$个环,再选出$a-1$个放在前面

    只需要求出整行的第一类斯特林数即可

    $s1(n,k)$为$prodlimits_{i=0}^{n-1} (x+i)$的$k$次项系数

    分治+$fft$即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #define ll long long
    12 #define db double
    13 #define inf 2139062143
    14 #define MAXN 100100
    15 #define MOD 998244353
    16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
    17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
    18 #define ren for(register int i=fst[x];i;i=nxt[i])
    19 #define pls(a,b) (a+b)%MOD
    20 #define mns(a,b) (a-b+MOD)%MOD
    21 #define mul(a,b) (1LL*(a)*(b))%MOD
    22 #define pb(a) push_back(a)
    23 using namespace std;
    24 inline int read()
    25 {
    26     int x=0,f=1;char ch=getchar();
    27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    28     while(isdigit(ch)) {x=x*10+(ch&15);ch=getchar();}
    29     return x*f;
    30 }
    31 int n,a,b,fac[MAXN<<1],ifac[MAXN<<1],l2[MAXN<<2],pw[30],ipw[30];
    32 int A[MAXN<<2],B[MAXN<<2],rev[MAXN<<2];
    33 int C(int n,int m) {return mul(mul(fac[n],ifac[m]),ifac[n-m]);}
    34 vector<int> vec[MAXN];
    35 int q_pow(int bas,int t,int res=1)
    36 {
    37     for(;t;bas=mul(bas,bas),t>>=1)
    38         if(t&1) res=mul(res,bas);return res;
    39 }
    40 void ntt(int *a,int n,int f)
    41 {
    42     rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
    43     for(int i=1;i<n;i<<=1)
    44     {
    45         int wn=f>0?pw[l2[i]+1]:ipw[l2[i]+1];
    46         for(int j=0;j<n;j+=i<<1)
    47         {
    48             for(int k=0,w=1,x,y;k<i;k++,w=mul(w,wn))
    49                 x=a[k+j],y=mul(a[i+j+k],w),a[j+k]=pls(x,y),a[i+j+k]=mns(x,y);
    50         }
    51     }
    52     if(f==1) return ;int nv=q_pow(n,MOD-2);
    53     rep(i,0,n-1) a[i]=mul(a[i],nv);
    54 }
    55 void solve(int *a,int *b,int lmt)
    56 {
    57     ntt(a,lmt,1);ntt(b,lmt,1);rep(i,0,lmt-1) a[i]=mul(a[i],b[i]);
    58     ntt(a,lmt,-1);
    59 }
    60 void Div(int l,int r,ll lmt=0)
    61 {
    62     if(l==r) return ;int mid=(l+r)>>1,lg;
    63     Div(l,mid);Div(mid+1,r);lg=l2[r-l+1]+1,lmt=1<<lg;
    64     rep(i,0,lmt-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1)),A[i]=B[i]=0;
    65     rep(i,0,vec[l].size()-1) A[i]=vec[l][i];
    66     rep(i,0,vec[mid+1].size()-1) B[i]=vec[mid+1][i];
    67     solve(A,B,lmt);vec[l].clear();vec[mid+1].clear();
    68     rep(i,0,lmt-1) vec[l].pb(A[i]);
    69 }
    70 int main()
    71 {
    72     n=read(),a=read(),b=read();fac[0]=ifac[0]=fac[1]=ifac[1]=1;
    73     if(n==1) return putchar((a==1&&b==1)?'1':'0'),0;
    74     rep(i,2,n<<1) fac[i]=mul(fac[i-1],i),ifac[i]=mul(MOD-MOD/i,ifac[MOD%i]);
    75     rep(i,2,n) ifac[i]=mul(ifac[i],ifac[i-1]);l2[0]=-1;rep(i,1,n<<2)
    76     {
    77         l2[i]=l2[i>>1]+1;if(!pw[l2[i]])
    78             pw[l2[i]]=q_pow(3,(MOD-1)/i),ipw[l2[i]]=q_pow(pw[l2[i]],MOD-2);
    79     }
    80     rep(i,0,n-2) vec[i].pb(i),vec[i].pb(1);Div(0,n-2);
    81     if(a+b-2>n-1) return putchar('0'),0;
    82     printf("%d
    ",mul(vec[0][a+b-2],C(a+b-2,a-1)));
    83 }
    View Code
  • 相关阅读:
    P4127 [AHOI2009]同类分布
    区间DP
    P3146 [USACO16OPEN]248
    P1241 括号序列
    P2858 [USACO06FEB]奶牛零食Treats for the Cows
    P2602 [ZJOI2010]数字计数&P1239 计数器&P4999 烦人的数学作业
    数位DP
    jquery生成元素注册事件无效,及事件委托的使用
    Jquery ajax运用执行顺序有误怎么解决
    html页面输入框input的美化
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/10692645.html
Copyright © 2011-2022 走看看