A
发现只可能是一个顶点向三个方向延展,答案就是2*(n(n-1))^2
D
思路与上一场的F一致,也是建立Trie,然后对子树进行二维数点即可,由于思路类似,这题不给出代码(实际上是博主太懒没写)。
E
容易发现只有最前面一段相同的序列插入时才有两种选择,设最前面一段长度是x,则答案是2^(x-1)
H
裸DP,先用背包求出f(i)表示花费i天最多得几分。合并时g(i,j)表示花了i天挂j门课时最多得分。转移复杂度O(nt^2p),代码略
J
结论题。
容易发现这个是一个排列,设排列为π,第i个数为π(i),逆序对的个数为n(π),则sgn(π)=(-1)^n(π)。
而sgn(π)=Π(π(i)-π(j))/(i-j)=Π(ia-ja)/(i-j)=a^(p(p-1)/2)≡a^((p-1)/2)(mod p)
直接计算a^((p-1)/2)即可,记得开int128
K
首先转化成i&j=k然后求后缀最大值,然后可以求k∈i,j时max(A),max(B),min(A),min(B),两两相乘的最大值即可,这个可以用FWT求出。

#include<bits/stdc++.h> using namespace std; const int N=263000,mod=998244353; int n,Amn[N],Amx[N],Bmn[N],Bmx[N]; int main() { int T;scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0,x;i<n;++i)scanf("%d",&x),Amn[i]=Amx[i]=x; for(int i=0,x;i<n;++i)scanf("%d",&x),Bmn[i]=Bmx[i]=x; int m=1;while(m<n)m<<=1; for(int i=n;i<m;++i)Amx[i]=Bmx[i]=-1e9,Amn[i]=Bmn[i]=1e9; for(int i=1;i<m;i<<=1) for(int j=0;j<m;j+=i<<1) for(int k=0;k<i;++k) { Amn[j+k]=min(Amn[j+k],Amn[j+k+i]); Bmn[j+k]=min(Bmn[j+k],Bmn[j+k+i]); Amx[j+k]=max(Amx[j+k],Amx[j+k+i]); Bmx[j+k]=max(Bmx[j+k],Bmx[j+k+i]); } int ans=0; long long mx=-1e18; for(int i=n-1;~i;--i) { mx=max(mx,1ll*Amn[i]*Bmn[i]); mx=max(mx,1ll*Amx[i]*Bmn[i]); mx=max(mx,1ll*Amn[i]*Bmx[i]); mx=max(mx,1ll*Amx[i]*Bmx[i]); ans=(ans+mx%mod+mod)%mod; } printf("%d ",ans); } }
L
略,题目好臭
持续更新中……