1. 程式人生 > 其它 >21杭電多校第二場

21杭電多校第二場

A

簽到題,對於一個正方體,有\(8\)種頂點均在正方體頂點上滿足條件的正三角形

顯然\(Ans=\sum\limits_{i=1}^{n-1}8i^3=8(\frac{n(n-1)}{2})^2=2(n-1)n\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll n,inv2;
ll qp(ll x,ll t,ll res=1)
{
	for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;
}
int main()
{
	inv2=qp(2,MOD-2);ll ans;rep(T,1,read())
	{
		n=read()%MOD;n=mns(n,1);ans=mul(n,n+1);
		ans=mul(ans,ans);ans=mul(ans,2);printf("%d\n",ans);
	}
}

B

樹鏈剖分維護二次函式,每次新增都是新增一段二次函式

平移後變成\(ax^2+bx+c\)的形式,其中\(x\)為線段樹的橫座標,這樣\(a,b,c\)可加,能直接維護

每次單點查詢得到答案

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,nxt[MAXN<<1],fst[MAXN],to[MAXN<<1],cnt,val[MAXN];
int sz[MAXN],dep[MAXN],fa[MAXN],hvs[MAXN],bl[MAXN],in[MAXN],tot;
void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
void dfs(int x,int pa)
{
    sz[x]=1,fa[x]=pa;
	ren if(to[i]^pa)
    {
		dep[to[i]]=dep[x]+1;dfs(to[i],x);
		sz[x]+=sz[to[i]],hvs[x]=sz[to[i]]>sz[hvs[x]]?to[i]:hvs[x];
	}
}
void Dfs(int x,int anc)
{
    bl[x]=anc,in[x]=++tot;if(!hvs[x]) return ;Dfs(hvs[x],anc);
    ren if(to[i]^fa[x]&&to[i]^hvs[x]) Dfs(to[i],to[i]);
}
ll taga[MAXN<<2],tagb[MAXN<<2],tagc[MAXN<<2];
void build(int k,int l,int r)
{
	taga[k]=tagb[k]=tagc[k]=0;if(l==r) return ;
	int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
void pshd(int k)
{
    taga[k<<1]+=taga[k],taga[k<<1|1]+=taga[k];
	tagb[k<<1]+=tagb[k],tagb[k<<1|1]+=tagb[k];
	tagc[k<<1]+=tagc[k],tagc[k<<1|1]+=tagc[k];
    taga[k]=tagb[k]=tagc[k]=0LL;
}
void mdf(int k,int l,int r,int a,int b,ll A,ll B,ll C)
{
    if(a<=l&&r<=b) {taga[k]+=A,tagb[k]+=B,tagc[k]+=C;return ;}
    int mid=l+r>>1;if(taga[k]!=0||tagb[k]!=0||tagc[k]!=0) pshd(k);
    if(a<=mid) mdf(k<<1,l,mid,a,b,A,B,C);
	if(b>mid) mdf(k<<1|1,mid+1,r,a,b,A,B,C);
}
ll query(int k,int l,int r,int x)
{
    if(l==r) return taga[k]*x*x+tagb[k]*x+tagc[k];int mid=l+r>>1;
    if(taga[k]!=0||tagb[k]!=0||tagc[k]!=0) pshd(k);
    return x<=mid?query(k<<1,l,mid,x):query(k<<1|1,mid+1,r,x);
}
inline int lca(int a,int b)
{
	for(;bl[a]!=bl[b];a=fa[bl[a]])
        if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
    if(in[a]>in[b]) swap(a,b);return a;
}
inline ll sqr(ll x){return x*x;}
void work(int a,int b)
{
	int z=lca(a,b),l=0,r=0,tmp=dep[a]+dep[b]-2*dep[z]+1;
	mdf(1,1,n,in[z],in[z],0,0,sqr(dep[a]-dep[z]+1));
    for(;bl[a]!=bl[z];a=fa[bl[a]])
    {
    	l=r+1,r+=dep[a]-dep[bl[a]]+1;
		mdf(1,1,n,in[bl[a]],in[a],1,-2LL*(in[a]+l),sqr(in[a]+l));
	}
	l=r+1,r+=dep[a]-dep[z];
	if(in[a]>in[z]) mdf(1,1,n,in[z]+1,in[a],1,-2LL*(in[a]+l),sqr(in[a]+l));
	l=tmp+1;
	for(;bl[b]!=bl[z];b=fa[bl[b]])
    {
    	r=l-1,l-=dep[b]-dep[bl[b]]+1;
		mdf(1,1,n,in[bl[b]],in[b],1,2LL*(r-in[b]),sqr(in[b]-r));
	}
	r=l-1,l-=dep[b]-dep[z];
	if(in[b]>in[z]) mdf(1,1,n,in[z]+1,in[b],1,2LL*(r-in[b]),sqr(in[b]-r));
}
inline ll solve(int a){return query(1,1,n,in[a]);}
int main()
{
    n=read();int a,b,c;
    rep(i,2,n) a=read(),b=read(),add(a,b),add(b,a);
    int q=read();dfs(1,0);Dfs(1,1);
    build(1,1,n);
    while(q--)
    {
		c=read(),a=read();if(c&1) b=read();
		if(c&1) work(a,b);else printf("%lld\n",solve(a));
	}
}

C

先處理出從\(z\)出發的最短路,若\(dis_x\neq dis_y\)則顯然勝負已分

對於\(dis_x=dis_y\)的情況,若均不能到達則為平局

否則設\(f[x][y][k]\)表示\(Alice\)\(x\)點,\(Bob\)\(y\)點,現在該誰走的勝負情況

\(DP\)即可,二者均只會選擇對自己最優的後繼狀態,這個轉移只會沿著最短路邊轉移,狀態很少

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,f[1010][1010][2],dis[1010],q[1010],hd,tl,z;
vector<int> G[1010],H[1010];vector<pii> del;
int dp(int x,int y,int k)
{
	if(!k&&(x==z||y==z))
	{
		if(x==z&&y==z) return 2;
		else return x==z?1:3;
	}
	if(f[x][y][k]) return f[x][y][k];
	if(!k)
	{
		f[x][y][k]=3;for(auto i:H[x]) if(i!=y||i==z)
			f[x][y][k]=min(f[x][y][k],dp(i,y,k^1));
	}
	else 
	{
		f[x][y][k]=1;for(auto i:H[y]) if(i!=x||i==z)
			f[x][y][k]=max(f[x][y][k],dp(x,i,k^1));
	}
	del.pb({x,y});return f[x][y][k];
}
int main()
{
	int x,y,t,a,b;rep(T,1,read())
	{
		n=read(),m=read(),x=read(),y=read(),z=read();
		rep(i,1,n) dis[i]=inf,G[i].clear();
		rep(i,1,m) a=read(),b=read(),G[a].pb(b),G[b].pb(a);
		q[hd=tl=1]=z,dis[z]=0;
		while(hd<=tl)
		{
			t=q[hd++];for(auto v:G[t])
				if(dis[v]==inf) dis[v]=dis[t]+1,q[++tl]=v;
		}
		if(dis[x]!=dis[y]) {puts(dis[x]<dis[y]?"1":"3");continue;}
		if(dis[x]==inf) {puts("2");continue;}
		rep(i,1,n) H[i].clear();
		rep(i,1,n) for(auto v:G[i]) if(dis[v]==dis[i]+1) H[v].pb(i);
		printf("%d\n",dp(x,y,0));for(auto x:del) f[x.fi][x.se][0]=f[x.fi][x.se][1]=0;
	}
}

D

對於每個查詢先不考慮異或的限制,相當於求有多少個\(i\)滿足\(l\le i\le r\)\(las_i< l\)

令每個點座標為\((las_i,i)\),可以用掃描線樹狀陣列解決

而對於異或的限制,在\(trie\)樹上查詢,可以得到一些節點,只有經過這些節點的值對於這次查詢才有意義

因此我們可以把詢問放到每個\(trie\)樹的節點上,插入值時同樣把這個點的座標加入經過的所有節點

這樣對於\(trie\)樹的所有節點都掃描線二位數點就可以解決問題

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,g[MAXN],c[MAXN],ans[MAXN],res;
int tr[MAXN*18][2],tot,las[MAXN],pos[MAXN];
void mdf(int x,int w){for(;x<=n;x+=x&-x) c[x]+=w;}
int query(int x,int res=0){for(;x;x-=x&-x) res+=c[x];return res;}
struct node{int l,r,x,id;};
bool operator < (node &a,node &b)
{
	if(a.x!=b.x) return a.x<b.x;
	if(a.r!=b.r) return a.r<b.r;
	return a.id<b.id;
}
vector<node> vec[MAXN*18];
inline void ins(int x,int id)
{
	int p=0,t;dwn(i,17,0)
	{
		t=(x>>i)&1;if(!tr[p][t]) tr[p][t]=++tot;
		p=tr[p][t];vec[p].pb({0,id,las[id],0});
	}
}
inline void insq(int l,int r,int a,int b,int id)
{
	int t,res=0,p=0,g;
	dwn(i,17,0)
	{
		t=(a>>i)&1,g=(b>>i)&1;
		if(g)
		{
			if(tr[p][t]) {vec[tr[p][t]].pb({l,r,l-1,id});}
			if(tr[p][t^1]) p=tr[p][1^t];
			else {p=-1;break;}
		}
		else 
		{
			if(tr[p][t]) p=tr[p][t];
			else {p=-1;break;}
		}
	}
	if(~p) vec[p].pb({l,r,l-1,id});
}
int main()
{
	n=read();rep(i,1,n) g[i]=read(),pos[i]=-1;
	rep(i,1,n) las[i]=pos[g[i]],pos[g[i]]=i;
	rep(i,1,n) ins(g[i],i);
	m=read();int l,r,a,b;
	rep(i,1,m) {l=read(),r=read(),a=read(),b=read();insq(l,r,a,b,i);}
	rep(i,1,tot)
	{
		sort(vec[i].begin(),vec[i].end());
		for(auto x:vec[i])
			if(!x.id) mdf(x.r,1);
			else ans[x.id]+=query(x.r)-query(x.l-1);
		for(auto x:vec[i]) if(!x.id) mdf(x.r,-1);
	}
	rep(i,1,m) printf("%d\n",ans[i]);
}

(賽時直接莫隊可過

E

簽到題,只有最前面連續若干個相同的\(k\)個相同字元可以有不同方案,答案為\(2^{k-1}\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,ans;char s[MAXN];
int main()
{
	rep(T,1,read())
	{
		n=read();scanf("%s",s+1);ans=1;
		rep(i,2,n) if(s[i]==s[i-1]) ans=mul(ans,2);else break;
		printf("%d\n",ans);
	}
}

F

由於調和級數複雜度為\(nlogn\),因此對每個\(p\)可以分別計算

考慮\(FWT\)的過程,已知\(A[0],A[1],A[2]\)\(B[0],B[1],B[2]\)

由題目規定位運算的定義可知

\(C[0]=A[0]B[0]\)

\(C[2]=A[2]B[0]+A[0]B[2]+A[2]B[2]\\\quad \ \ \ =(A[0]+A[2])(B[0]+B[2])-A[0]B[0]\)

\(C[1]=A[0]B[1]+A[1]B[0]+A[1]B[1]+A[1]B[2]+A[2]B[1]\\\quad \ \ \ =(A[0]+A[1]+A[2])(B[0]+B[1]+B[2])-(A[0]+A[2])(B[0]+B[2])\)

則可令\(fwt\)過程為\(\{a_0,a_1,a_2\}\rightarrow\{a_0,a_0+a_1+a_2,a_0+a_2\}\)

\(ifwt\)過程為\(\{a_0,a_1,a_2\}\rightarrow\{a_0,a_1-a_2,a_2-a_0\}\)

每次\(fwt\)後再按題意計算即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 600100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) ((a-(b))%MOD+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,a[MAXN],b[MAXN],c[MAXN],ans,A[MAXN],B[MAXN];
void trans(int &a,int &b,int &c)
{
	c=pls(c,a),b=pls(b,c);
}
void itrans(int &a,int &b,int &c)
{
	b=mns(b,c),c=mns(c,a);
}
void fwt(int *a,int n,int t)
{
	for(int i=1;i<n;i*=3) for(int j=0;j<n;j+=i*3) rep(k,0,i-1)
		if(!t) trans(a[j+k],a[j+k+i],a[j+k+2*i]);
		else itrans(a[j+k],a[j+k+i],a[j+k+2*i]);
}
void solve(int *a,int *b,int n)
{
	fwt(a,n,0);fwt(b,n,0);
	rep(i,0,n-1) a[i]=mul(a[i],b[i]);fwt(a,n,1);
}
int main()
{
	n=read();
	rep(i,1,n) scanf("%d",&a[i]);
	rep(i,1,n) scanf("%d",&b[i]);
	rep(i,1,n) scanf("%d",&c[i]);
	rep(p,1,n)
	{
		int t=n/p,pw=1,lim=1;rep(i,1,t) A[i]=a[i],B[i]=b[i];
		while(lim<=t) lim*=3;solve(A,B,lim);
		rep(i,1,lim) pw=mul(pw,c[p]),ans=pls(ans,mul(pw,A[i]));
		rep(i,1,lim) A[i]=B[i]=0;
	}
	printf("%d\n",ans);
}

G

很容易想到線段樹維護矩陣,樸素的想法是維護一個\(6\times 6\)的矩陣,但事實上並不需要

考慮二三操作,相當於對行向量\((a,b)\)進行矩陣乘一個矩陣,即乘以\(\begin{pmatrix}3&3\\2&-2\end{pmatrix}\)\(\begin{pmatrix}0 &1\\1&0\end{pmatrix}\)

對於線段樹每個節點維護\(\sum a_i,\sum b_i,\sum a_i^2,\sum b_i^2,\sum a_ib_i,tag_a,tag_b,tag_m\),其中\(tag_a,tag_b\)表示加法標記,\(tag_m\)表示矩陣乘法的標記

對於加法維護的各項容易推出,考慮乘一個矩陣\(\begin{pmatrix}c&d\\e&f\end{pmatrix}\)的影響

\(\sum a_i\rightarrow c\sum a_i+e\sum b_i\)\(\sum b_i\rightarrow d\sum a_i+f\sum b_i\)

\(\sum a_ib_i\rightarrow\sum (ca_i+eb_i)(da_i+fb_i)=cd\sum a_i^2+ef\sum b_i^2+(cf+ed)\sum a_ib_i\),由之前維護的值可以轉移得到;\(\sum a_i^2,\sum b_i^2\)同理

注意\(tag_a,tag_b\)同樣需要變動,優先進行矩陣的\(tag\)運算因此需要將原先存在的加法\(tag\)變為先矩乘之後的值

例如\(ca+eb+tag_a'=c(a+tag_a)+e(b+tag_b)\)\(tag_a\rightarrow c\ tag_a+e\ tag_b\)\(tag_b\)同理

這樣每次\(pushdown\)的時候需要優先進行\(tag_m\)的運算再\(pushdown\)加法\(tag\)

查詢普通區間查詢\(\sum a_ib_i\)即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 200100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,a[MAXN],b[MAXN];
inline void inc(ll &x,int y){x=pls(x,y);}
struct mat 
{
	int a[2][2];
	mat(){a[0][0]=a[1][1]=1,a[0][1]=a[1][0]=0;}
	mat operator *(const mat &x)
	{
		mat res;
		rep(i,0,1) rep(j,0,1)
		{
			res.a[i][j]=0;rep(k,0,1)
				res.a[i][j]=pls(res.a[i][j],mul(a[i][k],x.a[k][j]));
		}
		return res;
	}
}exc,trans,one;
struct node{mat tagm;ll s[2],s2[2],tag[2],ans;}tr[MAXN<<2];
inline void upd(int k)
{
	tr[k].ans=pls(tr[k<<1].ans,tr[k<<1|1].ans);
	rep(i,0,1) tr[k].s[i]=pls(tr[k<<1].s[i],tr[k<<1|1].s[i]);
	rep(i,0,1) tr[k].s2[i]=pls(tr[k<<1].s2[i],tr[k<<1|1].s2[i]);
}
inline ll sqr(ll x){return mul(x,x);}
void build(int k,int l,int r)
{
	if(l==r)
	{
		tr[k].tag[0]=tr[k].tag[1]=0;
		tr[k].s[0]=a[l],tr[k].s[1]=b[l];
		tr[k].s2[0]=sqr(a[l]);tr[k].s2[1]=sqr(b[l]);
		tr[k].ans=mul(a[l],b[l]);
		return ;
	}
	int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
	upd(k);
}
inline void Add(int k,int l,int r,int t,int x)
{
	if(!x) return ;inc(tr[k].tag[t],x);
	inc(tr[k].s2[t],pls(mul(tr[k].s[t],2*x),mul(mul(x,x),r-l+1)));
	inc(tr[k].ans,mul(x,tr[k].s[t^1]));
	inc(tr[k].s[t],mul(r-l+1,x));
}
inline void Mdf(int k,int l,int r,mat m)
{
	tr[k].tagm=tr[k].tagm*m;
	int a=m.a[0][0],b=m.a[1][0],c=m.a[0][1],d=m.a[1][1],p,q,tmp;
	p=tr[k].s2[0],q=tr[k].s2[1],tmp=tr[k].ans;
	tr[k].ans=mul(tr[k].ans,pls(mul(a,d),mul(b,c)));
	inc(tr[k].ans,pls(mul(mul(a,c),p),mul(mul(b,d),q)));
	tr[k].s2[0]=pls(mul(p,sqr(a)),mul(q,sqr(b)));
	inc(tr[k].s2[0],mul(mul(a,b),mul(tmp,2)));
	tr[k].s2[1]=pls(mul(p,sqr(c)),mul(q,sqr(d)));
	inc(tr[k].s2[1],mul(mul(c,d),mul(tmp,2)));
	p=tr[k].s[0],q=tr[k].s[1];
	tr[k].s[0]=pls(mul(a,p),mul(b,q));
	tr[k].s[1]=pls(mul(c,p),mul(d,q));
	p=tr[k].tag[0],q=tr[k].tag[1];
	tr[k].tag[0]=pls(mul(a,p),mul(b,q));
	tr[k].tag[1]=pls(mul(c,p),mul(d,q));
}
void pshd(int k,int l,int r,int mid)
{
	Mdf(k<<1,l,mid,tr[k].tagm);Mdf(k<<1|1,mid+1,r,tr[k].tagm);
	rep(i,0,1)
		Add(k<<1,l,mid,i,tr[k].tag[i]),
		Add(k<<1|1,mid+1,r,i,tr[k].tag[i]);
	tr[k].tagm=one;rep(i,0,1) tr[k].tag[i]=0;
}
void add(int k,int l,int r,int a,int b,int t,int x)
{
	if(a<=l&&r<=b) {Add(k,l,r,t,x);return ;}
	int mid=l+r>>1;pshd(k,l,r,mid);
	if(a<=mid) add(k<<1,l,mid,a,b,t,x);
	if(b>mid) add(k<<1|1,mid+1,r,a,b,t,x);
	upd(k);
}
void mdf(int k,int l,int r,int a,int b,mat x)
{
	if(a<=l&&r<=b) {Mdf(k,l,r,x);return ;}
	int mid=l+r>>1;pshd(k,l,r,mid);
	if(a<=mid) mdf(k<<1,l,mid,a,b,x);
	if(b>mid) mdf(k<<1|1,mid+1,r,a,b,x);
	upd(k);
}
ll query(int k,int l,int r,int a,int b)
{
	if(a<=l&&r<=b) return tr[k].ans;
	int mid=l+r>>1;ll res=0;pshd(k,l,r,mid);
	if(a<=mid) res=query(k<<1,l,mid,a,b);
	if(b>mid) res=pls(query(k<<1|1,mid+1,r,a,b),res);
	return res;
}
int main()
{
	n=read();rep(i,1,n) a[i]=read(),b[i]=read();
	exc.a[0][1]=exc.a[1][0]=1,exc.a[0][0]=exc.a[1][1]=0;
	trans.a[0][0]=trans.a[0][1]=3,trans.a[1][0]=2,trans.a[1][1]=MOD-2;
	one.a[0][0]=one.a[1][1]=1,one.a[0][1]=one.a[1][0]=0;
	build(1,1,n);int l,r,x,t;
	rep(Q,1,read())
	{
		t=read();
		if(t==1) {t=read(),l=read(),r=read(),x=read();add(1,1,n,l,r,t,x);}
		else 
		{
			l=read(),r=read();
			if(t==2) mdf(1,1,n,l,r,trans);
			else if(t==3) mdf(1,1,n,l,r,exc);
			else printf("%lld\n",query(1,1,n,l,r));
		}
	}
}

H

簡單\(dp\)組合

\(dp\)出每門課\(i\)花費\(j\)時間最多可以獲得多少分

再設\(dp[i][j][k]\)表示前\(i\)門課花了\(j\)時間掛了\(k\)門課獲得的最大分數,用之前處理出的陣列轉移

最後對所有合法答案取\(max\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define w first
#define v second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,p,f[55][550],dp[55][550][5],ans;
vector<pii> vec[55];
map<string,int> hsh;
int main()
{
	rep(T,1,read())
	{
		n=read();string s;int a,b;
		rep(i,1,n) {cin>>s;hsh[s]=i;}
		m=read();rep(i,1,m) {cin>>s;a=read(),b=read();vec[hsh[s]].pb({a,b});}
		m=read(),p=read();
		rep(i,1,n) {f[i][0]=0;rep(j,1,m) f[i][j]=-inf/2;}
		rep(i,1,n) for(auto x:vec[i])
			dwn(j,m,x.v) f[i][j]=min(max(f[i][j],f[i][j-x.v]+x.w),100);
		rep(i,0,n) rep(j,0,m) rep(k,0,p) dp[i][j][k]=-inf/2;
		dp[0][0][0]=0;
		rep(i,1,n) rep(j,0,m) rep(k,0,j) rep(t,0,p)
			if(f[i][j-k]>=60) dp[i][j][t]=max(dp[i][j][t],dp[i-1][k][t]+f[i][j-k]);
			else if(t) dp[i][j][t]=max(dp[i][j][t],dp[i-1][k][t-1]+f[i][j-k]);
		ans=-1;rep(i,0,m) rep(j,0,p) ans=max(ans,dp[n][i][j]);
		printf("%d\n",ans);hsh.clear();rep(i,1,n) vec[i].clear();
	}
}

I

奇妙列舉 咕

J

可以發現,最終得到的數列一定是一個長度為\(P-1\)的排列

令這個排列為\(\pi\),排列中第\(i\)個數為\(\pi(i)\),排列的逆序對數為\(n(\pi)\)\(sgn(\pi)=(-1)^{n(\pi)}\)

\[sgn(\pi)=\frac{\prod_{0<i<j\le p-1}\pi(j)-\pi(i)}{\prod_{0<i<j\le p-1}j-i}=\prod_{0<i<j\le p-1} \frac{\pi(j)-\pi(i)}{j-i}=\prod_{0<i<j\le p-1}\frac{(ja)\%P-(ia)\%P}{j-i} \]

想要消掉這個取模,考慮對\(sgn(\pi)\)取模,即:

\[\begin{aligned} sgn(\pi) &\equiv \prod_{0<i<j\le p-1}\frac{(ja)\%P-(ia)\%P}{j-i} (mod\ \ P)\\ sgn(\pi) &\equiv \prod_{0<i<j\le p-1}\frac{a\cdot (j-i)\%P}{j-i} (mod\ \ P)\\ sgn(\pi) &\equiv a^\frac{P(P-1)}{2} \prod_{0<i<j\le p-1}(j-i)\cdot inv(j-i)\ \ (mod\ \ P)\\ sgn(\pi) &\equiv a^\frac{P(P-1)}{2}\ \ (mod\ \ P)\\ \end{aligned} \]

只需要用快速冪判斷\(a^\frac{P(P-1)}{2}\ \ (mod\ \ P)\)是否等於\(1\)即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) ((__int128)(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll a,MOD; 
ll qp(ll x,ll t,ll res=1)
{
	for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);
	return res;
}
int main()
{
	rep(T,1,read())
	{
		a=read(),MOD=read();
		puts((qp(a,(MOD-1)/2)==1LL)?"0":"1");
	}
}

K

\(i\&j=k\),則說明\(k\)的二進位制表示是\(i,j\)的子集,對於一個\(k\)需要考慮所有這樣的數

\(f_i\)表示所有能轉移到\(i\)\(a\)的最大值,則\(f_i=max\{a_j\},i\subseteq j\)

列舉所有顯然複雜度過高,可以每次只向減少\(1\)\(1\)的數轉移即\(f_i=max\{f_j\},j=i|(1<<k)\),複雜度\(nlogn\)

又由於\(a,b\)存在負數,因此需要維護\(maxa,mina,maxb,minb\),最後的答案一定可以從這\(2\times2\)種情況中得到

對每個點再求一次後綴\(max\)即為所求

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 300100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,mxa[MAXN],mxb[MAXN],mna[MAXN],mnb[MAXN],t=1;
ll ans[MAXN],res;
int main()
{
	rep(T,1,read())
	{
		n=read();t=1;while((1<<t)<n) t++;
		rep(i,0,n-1) {scanf("%d",&mxa[i]);mna[i]=mxa[i];}
		rep(i,0,n-1) {scanf("%d",&mxb[i]);mnb[i]=mxb[i];}
		dwn(i,n-1,0) rep(j,0,t) if((i>>j)&1) 
			mxa[i^(1<<j)]=max(mxa[i^(1<<j)],mxa[i]),
			mxb[i^(1<<j)]=max(mxb[i^(1<<j)],mxb[i]),
			mna[i^(1<<j)]=min(mna[i^(1<<j)],mna[i]),
			mnb[i^(1<<j)]=min(mnb[i^(1<<j)],mnb[i]);
		rep(i,0,n-1)
			ans[i]=max(1LL*mxa[i]*mxb[i],1LL*mxa[i]*mnb[i]),
			ans[i]=max(max(1LL*mna[i]*mxb[i],1LL*mna[i]*mnb[i]),ans[i]);
		res=ans[n-1];
		dwn(i,n-2,0) ans[i]=max(ans[i],ans[i+1]),res=pls(res,ans[i]);
		printf("%d\n",(res+MOD)%MOD);
	}
}

L

簽到題,暴力判斷即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char s[100100];int n;
int cheq()
{
	rep(i,1,n-5) 
		if(s[i]=='1'&&s[i+1]=='1'&&s[i+2]=='4'&&s[i+3]=='5'&&s[i+4]=='1'&&s[i+5]=='4')
			return 1;
	return 0;
}
int main()
{
	rep(T,1,read())
	{
		scanf("%s",s+1);n=strlen(s+1);
		puts(cheq()?"AAAAAA":"Abuchulaile");
	}
}