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

先将所有数的平方因子都消去,记录每个数的出现次数

对于一个满足条件的三元组\((i,j,k)\)一定满足以下两种情况之一:

  • \(i,j,k\)均不含有\(>\sqrt{M}\)的质因子
  • \(i,j,k\)中两个含有\(>\sqrt{M}\)的质因子

第一种情况的三元组不会太多,可以直接爆搜,注意搜索时从大到小枚举质数

第二种可以枚举\([\sqrt{M},M]\)范围内的质数\(p\),再枚举两个\(p\)的倍数,计算第三个较小数统计答案

第二部分复杂度小于\(\int_{\sqrt{M}}^M\ (\frac{M}{x})^2dx=M^2(\frac{1}{\sqrt{M}}-\frac{1}{M})<M\sqrt{M}\)

#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(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;
}
const int lim=1e5,val=sqrt(lim+0.5);ll ans;
int n,mxp,p[MAXN],tot,ntp[MAXN],mp[MAXN],w[MAXN],g[350][350];
int gcd(int a,int b) {return !b?a:gcd(b,a%b);}
int mem(int n=lim) 
{
    rep(i,2,n)
    {
        if(!ntp[i]) p[++tot]=i,mp[i]=i;
        rep(j,1,tot) if(i*p[j]>n) break;
            else {ntp[i*p[j]]=1,mp[i*p[j]]=p[j];if(i%p[j]==0) break;}
    }
    mxp=lower_bound(p+1,p+tot+1,val)-p;
    rep(i,1,val) rep(j,i,val) g[i][j]=gcd(i,j),g[i][j]=i*j/g[i][j]/g[i][j];
}
void dfs(int x,int a,int b,int c)
{
    if(!x)
    {
        if(a<=b&&b<=c) 
        {
            if(a==1)
            {
                if(b==1) ans+=(ll)w[1]*(w[1]-1)*(w[1]-2)/6;
                else ans+=(ll)w[b]*(w[b]-1)*w[1]/2;
            }
            else ans+=(ll)w[a]*w[b]*w[c];
        }
        return ;
    }
    dfs(x-1,a,b,c);
    if(a*p[x]<=lim&&b*p[x]<=lim) dfs(x-1,a*p[x],b*p[x],c);
    if(b*p[x]<=lim&&c*p[x]<=lim) dfs(x-1,a,b*p[x],c*p[x]);
    if(a*p[x]<=lim&&c*p[x]<=lim) dfs(x-1,a*p[x],b,c*p[x]);
}
int main()
{
    mem();int x,tmp,cnt,d;
    rep(T,1,read())
    {
        n=read();Fill(w,0);ans=0;
        rep(i,1,n)
        {
            x=read(),tmp=1;
            while(x>1) 
            {
                while(x>1&&x%(mp[x]*mp[x])==0) x/=mp[x],x/=mp[x];
                if(x>1&&x%mp[x]==0) tmp*=mp[x],x/=mp[x];
            }
            w[tmp]++;
        }
        dfs(mxp,1,1,1);
        rep(i,mxp+1,tot) rep(j,1,lim/p[i]) rep(k,j,lim/p[i])
        {
            if(j==k) ans+=1LL*w[1]*w[j*p[i]]*(w[j*p[i]]-1)/2;
            else ans+=1LL*w[j*p[i]]*w[k*p[i]]*w[g[j][k]];
        }
        printf("%lld\n",ans);
    }
}

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");
	}
}
posted @ 2021-07-30 19:02  jack_yyc  阅读(78)  评论(0编辑  收藏  举报