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\n",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\n",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)$为$\prod\limits_{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\n",mul(vec[0][a+b-2],C(a+b-2,a-1)));
83 }
View Code

 

posted @ 2019-04-11 21:15  jack_yyc  阅读(141)  评论(0编辑  收藏  举报