• 21杭电多校第二场


    A

    签到题,对于一个正方体,有(8)种顶点均在正方体顶点上满足条件的正三角形

    显然(Ans=sumlimits_{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
    ",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
    ",solve(a));
    	}
    }
    

    C

    先处理出从(z)出发的最短路,若(dis_x eq 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
    ",dp(x,y,0));for(auto x:del) f[x.fi][x.se][0]=f[x.fi][x.se][1]=0;
    	}
    }
    

    D

    对于每个查询先不考虑异或的限制,相当于求有多少个(i)满足(lle ile 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
    ",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
    ",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} ightarrow{a_0,a_0+a_1+a_2,a_0+a_2})

    (ifwt)过程为({a_0,a_1,a_2} ightarrow{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
    ",ans);
    }
    

    G

    很容易想到线段树维护矩阵,朴素的想法是维护一个(6 imes 6)的矩阵,但事实上并不需要

    考虑二三操作,相当于对行向量((a,b))进行矩阵乘一个矩阵,即乘以(egin{pmatrix}3&3\2&-2end{pmatrix})(egin{pmatrix}0 &1\1&0end{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)表示矩阵乘法的标记

    对于加法维护的各项容易推出,考虑乘一个矩阵(egin{pmatrix}c&d\e&fend{pmatrix})的影响

    (sum a_i ightarrow csum a_i+esum b_i)(sum b_i ightarrow dsum a_i+fsum b_i)

    (sum a_ib_i ightarrowsum (ca_i+eb_i)(da_i+fb_i)=cdsum a_i^2+efsum 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 ightarrow 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
    ",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
    ",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})<Msqrt{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
    ",ans);
        }
    }
    

    J

    可以发现,最终得到的数列一定是一个长度为(P-1)的排列

    令这个排列为(pi),排列中第(i)个数为(pi(i)),排列的逆序对数为(n(pi))(sgn(pi)=(-1)^{n(pi)})

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

    想要消掉这个取模,考虑对(sgn(pi))取模,即:

    [egin{aligned} sgn(pi) &equiv prod_{0<i<jle p-1}frac{(ja)\%P-(ia)\%P}{j-i} (mod P)\ sgn(pi) &equiv prod_{0<i<jle p-1}frac{acdot (j-i)\%P}{j-i} (mod P)\ sgn(pi) &equiv a^frac{P(P-1)}{2} prod_{0<i<jle 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},isubseteq j)

    枚举所有显然复杂度过高,可以每次只向减少(1)(1)的数转移即(f_i=max{f_j},j=i|(1<<k)),复杂度(nlogn)

    又由于(a,b)存在负数,因此需要维护(maxa,mina,maxb,minb),最后的答案一定可以从这(2 imes2)种情况中得到

    对每个点再求一次后缀(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
    ",(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");
    	}
    }
    
  • 相关阅读:
    死锁分析-(DML+DDL触发Server层死锁)
    archery 1.80推送工单到飞书webhook失败解决方案
    mysql执行计划 Select tables optimized away
    apparmor mysql_Ubuntu 上更改 MySQL 数据库数据存储目录
    查看docker容器的tcp连接(转)
    Mongo副本集搭建方式
    数据库字段命名方法
    C# DataGridview控件自动下拉到最后一行
    C# datagridview绑定List<string>显示的是数据长度
    DataGridView 清空数据
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/15081035.html
Copyright © 2020-2023  润新知