11.26 模拟赛

写的分基本全挂了非常的菜 

T1 password

题目大意:

$m$个模式串 求长度为$n$的串中包含所有$m$个串的方案数

$m\le4,len\le50$ $len=字符串总长度$

思路:

可以想到一个$n\times len \times 2^m$的dp

然后将状压部分转换成容斥 使用矩阵加速 矩阵i j 表示节点i - j的转移

(死于全集没写快速幂)

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<vector>
  8 #include<queue>
  9 #include<map>
 10 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
 11 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
 12 #define ren for(register int i=fst[x];i;i=nxt[i])
 13 #define Fill(x,t) memset(x,t,sizeof(x))
 14 #define ll long long
 15 #define inf 2139062143
 16 #define MAXN 1400
 17 #define MOD 998244353
 18 using namespace std;
 19 inline int read()
 20 {
 21     int x=0,f=1;char ch=getchar();
 22     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
 23     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
 24     return x*f;
 25 }
 26 inline int add(ll a,ll b) {return a+b<MOD?a+b:a+b-MOD;}
 27 char s[5][60];
 28 int n,m,ch[MAXN][10],fail[MAXN],sz,ed[MAXN],cnt;
 29 ll tot;
 30 void ins(int x)
 31 {
 32     int len=strlen(s[x]),pos=0;
 33     rep(i,0,len-1) 
 34     {
 35         if(!ch[pos][s[x][i]-'0']) ch[pos][s[x][i]-'0']=++sz;
 36         pos=ch[pos][s[x][i]-'0'];
 37     }
 38     cnt++,ed[pos]|=(1<<cnt);
 39 }
 40 int q[MAXN],l=1,r,vis[MAXN];
 41 void build()
 42 {
 43     int x;
 44     rep(i,0,9) if(ch[0][i]) q[++r]=ch[0][i];
 45     while(l<=r)
 46     {
 47         x=q[l++];
 48         rep(i,0,9) if(ch[x][i]) fail[ch[x][i]]=ch[fail[x]][i],q[++r]=ch[x][i];
 49         else ch[x][i]=ch[fail[x]][i];
 50         ed[x]|=ed[fail[x]];
 51     }
 52 }
 53 struct Mat
 54 {
 55     ll num[55][55];
 56     Mat(){Fill(num,0);}
 57     Mat operator * (const Mat &a) const
 58     {
 59         Mat res;
 60         rep(i,0,sz) rep(j,0,sz) rep(k,0,sz)
 61             res.num[i][j]=add(res.num[i][j],(num[i][k]*a.num[k][j])%MOD);
 62         return res;
 63     }
 64 };
 65 Mat res;
 66 ll calc(int x)
 67 {
 68     vis[x]=1;ll ans=res.num[0][x];
 69     rep(i,0,9) if(!vis[ch[x][i]]&&!ed[ch[x][i]]) ans=add(ans,calc(ch[x][i]));
 70     return ans;
 71 }
 72 ll q_pow(Mat x,ll t)
 73 {
 74     Fill(res.num,0);rep(i,0,sz) res.num[i][i]=1;
 75     for(;t;t>>=1,x=x*x)
 76         if(t&1) res=x*res;
 77     //rep(i,0,sz) {rep(j,0,sz) cout<<res.num[i][j]<<" ";puts("");}
 78     return calc(0);
 79 }
 80 ll qaq(ll bas,ll t)
 81 {
 82     ll res=1;
 83     for(;t;t>>=1,(bas*=bas)%=MOD)
 84         if(t&1) (res*=bas)%=MOD;
 85     return res;
 86 }
 87 int main()
 88 {
 89     freopen("password.in","r",stdin);
 90     freopen("password.out","w",stdout);
 91     m=read(),n=read();int ms=(1<<m)-1;Mat tmp;
 92     rep(i,1,m) scanf("%s",s[i]);tot=1;
 93     tot=qaq(10LL,n);
 94     rep(t,1,ms)
 95     {
 96         Fill(fail,0);Fill(ch,0);Fill(vis,0);Fill(tmp.num,0);Fill(ed,0);sz=cnt=0;
 97         rep(i,1,m) if(1&(t>>(i-1))) ins(i);
 98         build();rep(i,0,sz) if(!ed[i]) rep(j,0,9) tmp.num[i][ch[i][j]]++;
 99         if(cnt&1) tot=(tot+MOD-q_pow(tmp,n))%MOD;else tot=add(tot,q_pow(tmp,n));
100     }
101     printf("%lld\n",tot);
102 }
View Code

 

T2 paint

题目大意:

一个数列分成若干段 每段长度属于$[l,r]$ 设该段和为x 每一段的价值为$a*x^2+b*x+c$ 求最终的最大价值

思路:

看上去像是一个斜优 但是由于斜率和x坐标都不单调,还有长度的限制

考虑线段树分治 每个点可以对之后的一段区间造成影响 用线段树记录

对于每个点 我们将包含它的线段树上的节点的凸包搞出来 在每个凸包上二分出答案 并在这$log_n$个答案中取最优

(中间有结果会爆long long 所以特判了一波)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<map>
10 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
11 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
12 #define ren(x) for(register int i=fst[x];i;i=nxt[i])
13 #define Fill(x,t) memset(x,t,sizeof(x))
14 #define ll long long
15 #define inf 1152921504606846976LL
16 #define maxi 2147483647
17 #define MAXN 600100
18 #define MOD 998244353
19 using namespace std;
20 inline ll read()
21 {
22     ll x=0,f=1;char ch=getchar();
23     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
24     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
25     return x*f;
26 }
27 ll a,b,c,sum[MAXN],dp[MAXN];
28 int n,fst[MAXN],to[MAXN<<4],nxt[MAXN<<4],cnt,l,r;
29 vector <int> vec[MAXN];
30 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
31 void mdf(int k,int l,int r,int a,int b,int w)
32 {
33     if(l==a&&r==b) {add(k,w);return ;}
34     int mid=l+r>>1;
35     if(b<=mid) mdf(k<<1,l,mid,a,b,w);
36     else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,w);
37     else {mdf(k<<1,l,mid,a,mid,w);mdf(k<<1|1,mid+1,r,mid+1,b,w);}
38 }
39 int top,q[MAXN],tl;
40 struct Point
41 {
42     ll x,y,fi;int id;
43     Point operator - (const Point &a) const {return (Point){x-a.x,y-a.y,fi,id};}
44     bool operator < (const Point &a) const {return x<a.x;}
45     ll operator * (const Point &a) const {return (ll)x*a.y-y*a.x;}
46 }st[MAXN];
47 ll calc(int x,int y) {if(sum[y]-sum[x]>maxi&&a<0) return -inf;return dp[x]+a*(sum[y]-sum[x])*(sum[y]-sum[x])+c;}
48 void solve(int k,int l,int r)
49 {
50     top=tl=0;int mid;
51     ren(k) st[++top]=(Point){sum[to[i]],dp[to[i]]+a*sum[to[i]]*sum[to[i]]-b*sum[to[i]],dp[to[i]],to[i]};
52     if(top)
53     {
54         sort(st+1,st+top+1);q[++tl]=1;
55         rep(i,2,top)
56         {
57             if(st[i].fi<=-inf+100000000000000LL) continue;
58             while(tl>1&&(st[q[tl]]-st[q[tl-1]])*(st[i]-st[q[tl]])>=0LL) tl--;
59             q[++tl]=i;
60         }
61         rep(i,1,tl) vec[k].push_back(st[q[i]].id);
62     }
63     if(l==r)
64     {
65         int ml,mr,mid,res;
66         for(int t=k;t;t>>=1)
67         {
68             ml=0,res=mr=vec[t].size()-1;if(mr<0) continue;mr--; 
69             while(ml<=mr) {mid=ml+mr>>1;if(calc(vec[t][mid+1],l)<=calc(vec[t][mid],l)) mr=mid-1,res=mid;else ml=mid+1;}
70             dp[l]=max(calc(vec[t][res],l),dp[l]);
71         }
72         return ;
73     }
74     mid=l+r>>1;solve(k<<1,l,mid);solve(k<<1|1,mid+1,r);
75 }
76 int main()
77 {
78     freopen("paint.in","r",stdin);
79     freopen("paint.out","w",stdout);
80     n=read(),a=read(),b=read(),c=read(),l=read(),r=read();
81     rep(i,1,n) sum[i]=sum[i-1]+read(),dp[i]=-1LL<<60;
82     rep(i,0,n-l) mdf(1,0,n,i+l,min(i+r,n),i);
83     solve(1,0,n);printf("%lld\n",dp[n]+b*sum[n]);
84 }
View Code

 

T3 route

题目大意:

一棵树 一个路径的权值为这个路径上最小边的权值*权值和 求一条路径上最大值与最小值之差<m的路径的权值最大值

思路:

首先可以知道一个结论:

还是线段树分治 按边权排序后每条边对一个区间内边有影响

我们使用带撤销并查集维护这个图的直径 每个点的答案即为当前图的直径$\times$ 这个点的权值(由于从小到大加入边)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<map>
10 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
11 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
12 #define ren for(register int i=fst[x];i;i=nxt[i])
13 #define ren0 for(register int i=fst0[k];i;i=nxt0[i])
14 #define Fill(x,t) memset(x,t,sizeof(x))
15 #define ll long long
16 #define inf 2139062143
17 #define MAXN 170100
18 using namespace std;
19 inline int read()
20 {
21     int x=0,f=1;char ch=getchar();
22     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
23     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
24     return x*f;
25 }
26 int n,m,fa[MAXN],in[MAXN<<1],rnk[MAXN],l2[MAXN<<1];
27 int fst[MAXN],to[MAXN<<1],nxt[MAXN<<1],val[MAXN<<1],cnt,tot;
28 int nxt0[MAXN*20],fst0[MAXN<<2],to0[MAXN*20],top;
29 struct Edge{int u,v,w;}e[MAXN];
30 struct Path{int x,y;}g[MAXN];
31 struct Cancel{int x,y,rnk;ll len;Path a;}st[MAXN];
32 bool operator < (const Edge &a,const Edge &b) {return a.w<b.w;}
33 ll ans,dis[MAXN],f[20][MAXN<<1],dmt;
34 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
35 void Add(int u,int v) {nxt0[++cnt]=fst0[u],fst0[u]=cnt,to0[cnt]=v;}
36 int find(int x) {return x==fa[x]?x:find(fa[x]);}
37 void dfs(int x,int fa)
38 {
39     in[x]=tot;
40     ren if(to[i]!=fa) {f[0][++tot]=dis[to[i]]=dis[x]+val[i];dfs(to[i],x);f[0][++tot]=dis[x];}
41 }
42 ll calc(int x,int y)
43 {
44     if(in[x]>in[y]) swap(x,y);int t=l2[in[y]-in[x]+1];
45     return dis[x]+dis[y]-(min(f[t][in[x]],f[t][in[y]-(1<<t)+1])<<1);
46 }
47 Path merge(int x,int y,int xx,int yy)
48 {
49     int ax=x,ay=y;
50     if(calc(x,xx)>calc(ax,ay)) ax=x,ay=xx;
51     if(calc(x,yy)>calc(ax,ay)) ax=x,ay=yy;
52     if(calc(y,xx)>calc(ax,ay)) ax=y,ay=xx;
53     if(calc(y,yy)>calc(ax,ay)) ax=y,ay=yy;
54     if(calc(xx,yy)>calc(ax,ay)) ax=xx,ay=yy;
55     return (Path){ax,ay};
56 }
57 void Merge(int x,int y)
58 {
59     int u=find(x),v=find(y);
60     if(rnk[u]<rnk[v]) swap(u,v);
61     fa[v]=u,st[++top]=(Cancel){u,v,rnk[u],dmt,g[u]},g[u]=merge(g[u].x,g[u].y,g[v].x,g[v].y);
62     if(rnk[u]==rnk[v]) rnk[u]++;
63     dmt=max(dmt,calc(g[u].x,g[u].y));
64 }
65 void dlt()
66 {
67     int x=st[top].x,y=st[top].y;
68     fa[y]=y,rnk[x]=st[top].rnk,g[x]=st[top].a,dmt=st[top--].len;
69 }
70 void mdf(int k,int l,int r,int a,int b,int w)
71 {
72     if(l==a&&r==b) {Add(k,w);return ;}
73     int mid=l+r>>1;
74     if(b<=mid) mdf(k<<1,l,mid,a,b,w);
75     else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,w);
76     else {mdf(k<<1,l,mid,a,mid,w);mdf(k<<1|1,mid+1,r,mid+1,b,w);}
77 }
78 void solve(int k,int l,int r)
79 {
80     int pos=top,mid=l+r>>1;
81     ren0 Merge(e[to0[i]].u,e[to0[i]].v);
82     if(l==r) ans=max(ans,dmt*e[l].w);
83     else {solve(k<<1,l,mid);solve(k<<1|1,mid+1,r);}
84     while(top!=pos) dlt();
85 }
86 int main()
87 {
88     freopen("route.in","r",stdin);
89     freopen("route.out","w",stdout);
90     n=read(),m=read();int a,b,c;
91     rep(i,1,n-1) {a=read(),b=read(),c=read();add(a,b,c);add(b,a,c);e[i]=(Edge){a,b,c};}
92     dfs(1,0);sort(e+1,e+n);rep(i,1,n) fa[i]=i,g[i]=(Path){i,i};
93     rep(i,2,tot) l2[i]=l2[i>>1]+1;cnt=0;
94     rep(j,1,19) rep(i,1,tot) {if(i+(1<<j)-1>tot) break;f[j][i]=min(f[j-1][i],f[j-1][i+(1<<j-1)]);}
95     a=n-1;
96     dwn(i,n-1,1) {while(e[i].w-e[a].w<=m&&a) a--;mdf(1,1,n-1,a+1,i,i);}
97     solve(1,1,n-1);
98     printf("%lld\n",ans);
99 }
View Code

 

posted @ 2018-11-27 16:13  jack_yyc  阅读(238)  评论(0编辑  收藏  举报