睿频阿百川
ABC304G
说实话真不敢往那方面想
显然二分,然后我们就把数全部打到\(Tire\)树上
尝试让\(a_x\oplus a_y\ge mid\)匹配数量多,如果对于节点\(u\),\(mid\)深度为\(0\)则直接左右匹配再往重的那边子树走,如果为\(1\)就必须考虑两边子树,这看着不好做
实际上就算是递归两边子树也可做,因为不会产生更多的分叉,这个分讨一下即可
Show Code
// LUOGU_RID: 126326885
#include<bits/stdc++.h>//
using namespace std;
const int MAXN=2e5+5;///
int Tree[MAXN*30][2];
int cnt_node;
int Num[MAXN*30];
int n;
int a[MAXN];
void Insert(int x)
{//
int p=0;
for(int i=30;i>=0;i--)
{
int op=(x>>i)&1;
if(!Tree[p][op])
{
Tree[p][op]=++cnt_node;
}
p=Tree[p][op];
Num[p]++;
}
}
int Lit;
int dfs(int u1,int u2,int dep)
{
if(dep==-1)
{
if(u1==u2)
{
return 0;
}
else
{
return min(Num[u1],Num[u2]);
}
}
if((!u1)&&(dep!=30))
{
return 0;
}
if((!u2)&&(dep!=30))
{
return 0;
}
if(u1==u2)
{
if((Lit>>dep)&1)
{
return dfs(Tree[u1][0],Tree[u1][1],dep-1);
}
else
{
if(Num[Tree[u1][0]]>Num[Tree[u1][1]])
{
return Num[Tree[u1][1]]+min((Num[Tree[u1][0]]-Num[Tree[u1][1]])/2,dfs(Tree[u1][0],Tree[u1][0],dep-1));
}
else
{
return Num[Tree[u1][0]]+min((Num[Tree[u1][1]]-Num[Tree[u1][0]])/2,dfs(Tree[u1][1],Tree[u1][1],dep-1));
}
}
}
else
{
if((Lit>>dep)&1)
{
return dfs(Tree[u1][0],Tree[u2][1],dep-1)+dfs(Tree[u1][1],Tree[u2][0],dep-1);
}
else
{
if(Num[Tree[u1][0]]>Num[Tree[u2][1]]&&Num[Tree[u1][1]]<Num[Tree[u2][0]])
{
return Num[Tree[u2][1]]+Num[Tree[u1][1]]+min(min((Num[Tree[u1][0]]-Num[Tree[u2][1]]),(Num[Tree[u2][0]]-Num[Tree[u1][1]])),dfs(Tree[u1][0],Tree[u2][0],dep-1));
}
else if(Num[Tree[u1][0]]<Num[Tree[u2][1]]&&Num[Tree[u1][1]]>Num[Tree[u2][0]])
{
return Num[Tree[u2][0]]+Num[Tree[u1][0]]+min(min((Num[Tree[u1][1]]-Num[Tree[u2][0]]),(Num[Tree[u2][1]]-Num[Tree[u1][0]])),dfs(Tree[u1][1],Tree[u2][1],dep-1));
}
else
{
return min(Num[Tree[u1][0]],Num[Tree[u2][1]])+min(Num[Tree[u1][1]],Num[Tree[u2][0]]);
}
}
}
}
bool check(int mid)
{
Lit=mid;
// printf("%d??\n",dfs(0,0,30));
return dfs(0,0,30)>=(n+1)/2;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=2*n;i++)
{
scanf("%d",&a[i]);
Insert(a[i]);
}
int l=1;////
int r=(1<<30);
int Key=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))
{
Key=mid;
l=mid+1;
}
else
{
r=mid-1;
}
}
printf("%d\n",Key);
}
ABC290G
直接枚举往上割的子树然后在从大到小枚举深度割向下的边即可
感觉这个构造类似与\(k\)进制拆分
Show Code
#include<bits/stdc++.h>
using namespace std;
int T;
long long D,K;
long long X;
long long Siz[105];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&T);
while(T--)
{
scanf("%lld %lld %lld",&D,&K,&X);
long long Res=2e18;
for(int i=0;i<=D;i++)
{
__int128 Ne=1;
for(int j=1;j<=i+1;j++)
{
Ne*=K;
}
Ne=Ne-1;
Ne=(Ne/(K-1));
Siz[i]=Ne;
}
for(int i=0;i<=D;i++)
{
long long Now=Siz[i];
long long tot=1;
if(i==D)
{
tot--;
}
long long Det=Now-X;
if(Det<0)
{
continue;
}
for(int j=i-1;j>=0;j--)
{
tot+=(Det/Siz[j]);
Det%=Siz[j];
}
if(Det==0)
{
Res=min(Res,tot);
}
}
printf("%lld\n",Res);
}
}
ABC290Ex
神秘题
不难发现我们尽量让最大的放中间
如果\(n,m\)不为偶数的话我们一定得把大的放中间
如果均为偶数,实际上我们左右两边猫狗数量应该相同,因为如果不同一定可以通过调整使得答案更有
实际上两侧同样满足递增得性质,我们据此\(dp\)即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=305;
int n,m;
int a[MAXN];
int b[MAXN];
long long dp[MAXN*2][MAXN][MAXN];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
}
sort(a+1,a+1+n);
sort(b+1,b+1+m);
long long Res=0;
if(n&1)
{
if(m&1)
{
Res+=a[n];
}
for(int i=1;i<=m;i++)
{
Res+=b[i];
}
n--;
}
if(m&1)
{
for(int i=1;i<=n;i++)
{
Res+=a[i];
}
m--;
}
vector<pair<int,int> >V;
V.push_back(make_pair(0,0));
for(int i=1;i<=n;i++)
{
V.push_back(make_pair(a[i],0));
}
for(int i=1;i<=m;i++)
{
V.push_back(make_pair(b[i],1));
}
sort(V.begin(),V.end());
memset(dp,0x3f,sizeof(dp));
dp[0][0][0]=0;
int s0=0;
int s1=0;
for(int i=0;i<n+m;i++)
{
for(int j=0;j<=min(s0,n/2);j++)
{
for(int k=0;k<=min(s1,m/2);k++)
{
if(V[i+1].second==0)
{
int qj=(s0-j);
int qk=(s1-k);
if(qj<=n/2&&qk<=m/2)
{
dp[i+1][j][k]=min(dp[i+1][j][k],dp[i][j][k]+((long long)V[i+1].first*(m-2*qk)));
dp[i+1][j+1][k]=min(dp[i+1][j+1][k],dp[i][j][k]+((long long)V[i+1].first*(m-2*k)));
}
}
else
{
int qj=(s0-j);
int qk=(s1-k);
if(qj<=n/2&&qk<=m/2)
{
dp[i+1][j][k]=min(dp[i+1][j][k],dp[i][j][k]+((long long)V[i+1].first*(n-2*qj)));
dp[i+1][j][k+1]=min(dp[i+1][j][k+1],dp[i][j][k]+((long long)V[i+1].first*(n-2*j)));
}
}
}
}
if(V[i+1].second==0)
{
s0++;
}
else
{
s1++;
}
}
printf("%lld\n",Res+dp[n+m][n/2][m/2]);
}
ABC289G
一眼决策单调性
好吧,证明也很显,不过这里我们决策点得是\(B\)中的数,当然这样不劣
用一下分治即可
Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=2e5+5;
int n,m;
int x;
pair<int,int>C[MAXN];
int B[MAXN];
long long Ans[MAXN];
long long Cal(int x,int c)
{
int Ce=n-(lower_bound(B+1,B+1+n,c-C[x].first)-B)+1;
return ((long long)Ce*c);
}
void solve(int ql,int qr,int l,int r)
{
if(ql>qr)
{
return;
}
if(l==r)
{
for(int i=ql;i<=qr;i++)
{
Ans[C[i].second]=Cal(i,B[l]+C[i].first);
}
return;
}
int mid=(ql+qr)>>1;
long long Maxi=0;
int Key;
for(int i=l;i<=r;i++)
{
if(Cal(mid,B[i]+C[mid].first)>=Maxi)
{
Maxi=Cal(mid,B[i]+C[mid].first);
Key=i;
}
}
Ans[C[mid].second]=Maxi;
solve(ql,mid-1,Key,r);
solve(mid+1,qr,l,Key);
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&B[i]);
}
sort(B+1,B+1+n);
for(int i=1;i<=m;i++)
{
scanf("%d",&C[i].first);
C[i].second=i;
}
sort(C+1,C+1+m);
solve(1,m,1,n);
for(int i=1;i<=m;i++)
{
printf("%lld ",Ans[i]);
}
}
ABC288G
第一眼以为是找规律
结果这\(A,B\)之间是个线性变换,也确实是,类似于高维前缀和,直接求出逆即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=6e5+5;
int n;
int Pw[15];
int a[MAXN];
int b[MAXN];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
Pw[0]=1;
for(int i=1;i<=n;i++)
{
Pw[i]=Pw[i-1]*3;
}
//cerr<<Pw[n]<<endl;
for(int i=0;i<Pw[n];i++)
{
scanf("%d",&a[i]);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<Pw[n];j++)
{
b[j]=a[j];
a[j]=0;
}
for(int j=0;j<Pw[n];j++)
{
int op=(j/Pw[i])%3;
int ept=(j-op*Pw[i]);
if(op==1)
{
a[j]=b[ept]+b[ept+Pw[i]*2]-b[ept+Pw[i]];
}
else if(op==2)
{
a[j]=b[ept+Pw[i]]-b[ept];
}
else
{
a[j]=b[ept+Pw[i]]-b[ept+2*Pw[i]];
}
}
}
for(int i=0;i<Pw[n];i++)
{
printf("%d ",a[i]);
}
}
ABC287G
直接权值线段树即可
Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=2e6+5;
int n,q;
int op;
int x,y;
int a[MAXN];
int b[MAXN];
struct Seg{
int lc,rc;
int num;
long long date;
}Tree[MAXN*10];
int cnt_node;
int rt;
void Insert(int &p,int l,int r,int k,int x)
{
if(!p)
{
p=++cnt_node;
Tree[p].lc=Tree[p].rc=Tree[p].num=Tree[p].date=0;
}
Tree[p].num+=x;
Tree[p].date+=(long long)x*k;
if(l==r)
{
return;
}
int mid=(l+r)>>1;
if(k<=mid)
{
Insert(ls,l,mid,k,x);
}
else
{
Insert(rs,mid+1,r,k,x);
}
}
long long Query(int p,int l,int r,int k)
{
if(!p)
{
return 0;
}
if(l==r)
{
return (long long)k*l;
}
int mid=(l+r)>>1;
// printf("%d %d %d %d %d:::\n",l,r,k,Tree[rs].num,Tree[p].num);
if(Tree[rs].num<=k)
{
return Tree[rs].date+Query(ls,l,mid,k-Tree[rs].num);
}
else
{
return Query(rs,mid+1,r,k);
}
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&a[i],&b[i]);
Insert(rt,0,1e9,a[i],b[i]);
}
scanf("%d",&q);
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d %d",&x,&y);
Insert(rt,0,1e9,a[x],-b[x]);
a[x]=y;
Insert(rt,0,1e9,a[x],b[x]);
}
else if(op==2)
{
scanf("%d %d",&x,&y);
Insert(rt,0,1e9,a[x],-b[x]);
b[x]=y;
Insert(rt,0,1e9,a[x],b[x]);
}
else if(op==3)
{
scanf("%d",&x);
if(Tree[rt].num<x)
{
printf("-1\n");
}
else
{
printf("%lld\n",Query(rt,0,1e9,x));
}
}
}
}
ABC288Ex
什么狗霸体
最开始的思路记不到了,反正直接数位\(dp\)搞一下,不过有点难限制
正解的话先不考虑重复元素,这里数位\(dp\)搞一下没啥问题,然后考虑枚举\((i,j,k)\)表示有\(i\)个位置是出现次数为奇数的元素,有\(j\)个奇数次数的元素,有\(k\)个偶数次数的元素,这样的方案减一下刚好不重不漏得到没有重复元素的答案,最后再消消序即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=205;
int fac[MAXN];
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int n,m,x;
int g[MAXN];
int dp[35][MAXN];
int C[MAXN][MAXN];
int Even[MAXN][MAXN];
int Odd[MAXN][MAXN];
int Reg[MAXN][MAXN];
int c(int n,int m)
{
int rt=1;
for(int i=n-m+1;i<=n;i++)
{
rt=((long long)rt*i)%MOD;
}
int pt=1;
for(int i=1;i<=m;i++)
{
pt=((long long)pt*i)%MOD;
}
rt=((long long)rt*inv(pt,MOD))%MOD;
return rt;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
C[0][0]=1;
fac[0]=1;
for(int i=1;i<=MAXN-5;i++)
{
C[i][0]=1;
fac[i]=((long long)fac[i-1]*i)%MOD;
for(int j=1;j<=MAXN-5;j++)
{
C[i][j]=((long long)C[i-1][j]+C[i-1][j-1])%MOD;
}
}
scanf("%d %d %d",&n,&m,&x);
for(int l=1;l<=n;l++)
{
memset(dp,0,sizeof(dp));
dp[31][0]=1;
for(int i=30;i>=0;i--)
{
for(int j=0;j<=l;j++)
{
int Od=0,Ev=0;
for(int k=0;k<=j;k++)
{
if(k&1)
{
Od=((long long)Od+C[j][k])%MOD;
}
else
{
Ev=((long long)Ev+C[j][k])%MOD;
}
}
if((m>>i)&1)
{
for(int k=0;k+j<=l;k++)
{
int Ry=(l-k-j);
int Rtu=(Ry&1)^((x>>i)&1);
int Rst=1;
if(Rtu&1)
{
Rst=((long long)Rst*Od)%MOD;
}
else
{
Rst=((long long)Rst*Ev)%MOD;
}
Rst=((long long)Rst*C[l-j][k])%MOD;
dp[i][j+k]=((long long)dp[i][j+k]+((long long)dp[i+1][j]*Rst)%MOD)%MOD;
}
}
else
{
int Rtu=(x>>i)&1;
int Rst=1;
if(Rtu&1)
{
Rst=((long long)Rst*Od)%MOD;
}
else
{
Rst=((long long)Rst*Ev)%MOD;
}
dp[i][j]=((long long)dp[i][j]+((long long)dp[i+1][j]*Rst)%MOD)%MOD;
}
}
}
g[l]=0;
for(int i=0;i<=l;i++)
{
g[l]=((long long)g[l]+dp[0][i])%MOD;
}
}
Odd[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
for(int k=1;k<=i;k+=2)
{
Odd[i][j]=((long long)Odd[i][j]+((long long)Odd[i-k][j-1]*C[i][k])%MOD)%MOD;
}
}
}
Even[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
for(int k=2;k<=i;k+=2)
{
Even[i][j]=((long long)Even[i][j]+((long long)Even[i-k][j-1]*C[i][k])%MOD)%MOD;
}
}
}
for(int i=0;i<=n;i++)
{
for(int j=0;j<=i;j++)
{
Even[i][j]=((long long)Even[i][j]*inv(fac[j],MOD))%MOD;
Odd[i][j]=((long long)Odd[i][j]*inv(fac[j],MOD))%MOD;
// printf("%d %d:\n",i,j);
// printf("%d\n%d\n",Even[i][j],Odd[i][j]);
}
}
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
int Mul=1;
int Ptto=m-j+1;
for(int k=0;k<=n;k++)
{
int Wto=0;
Wto=Even[i][k];
Wto=((long long)Wto*Mul)%MOD;
Reg[i][j]=((long long)Reg[i][j]+Wto)%MOD;
Mul=((long long)Mul*Ptto)%MOD;
Ptto--;
if(Ptto<0)
{
break;
}
}
//printf("%d %d %d--\n",i,j,Reg[i][j]);
}
}
if(x==0)
{
g[0]=1;
//cerr<<"fic"<<endl;
}
for(int l=1;l<=n;l++)
{
for(int i=0;i<=l;i++)
{
for(int j=0;j<l;j++)
{
int Vto=((long long)C[l][i]*Odd[i][j])%MOD;
Vto=((long long)Vto*g[j])%MOD;
Vto=((long long)Vto*Reg[l-i][j])%MOD;
g[l]=((long long)g[l]-Vto+MOD)%MOD;
}
}
}
// cerr<<g[0]<<endl;
// for(int i=0;i<=n;i++)
// {
// printf("%d:: %d\n",i,g[i]);
// }
int Res=0;
for(int i=n;i>=0;i-=2)
{
int Tto=g[i];
Tto=((long long)Tto*c(m+(n-i)/2,(n-i)/2))%MOD;
Tto=((long long)Tto*inv(fac[i],MOD))%MOD;
Res=((long long)Res+Tto)%MOD;
}
printf("%d\n",Res);
}
ABC321G
狗霸体+1
不难发现\(a-b|x\),如果\(k=2\),直接可以算
如果\(k\ge3\),不难发现\(a^2-b^2\le x\),枚举\(a+b\),这样时间复杂度是因数和也不是很大
枚举完暴力跑背包即可,卡卡常
正解似乎不用背包,直接进制填即可
Show Code
#include<bits/stdc++.h>
using namespace std;//
const int MOD=998244353;
int n,x;
int Res=0;
map<int,int>Vis,Tmp;
void work(int d)
{
int rkt=(x/d);
int Use=Res;
if(rkt<10)
{
int Zptr=n-d;
int Zptl=rkt+1;
if(Zptl<=Zptr)
{
int Ztll=max(10,Zptl);
if(Ztll<=Zptr)
{
Res=((long long)Res+(10ll*(Zptr-Ztll+1))%MOD)%MOD;
}
for(int b=Zptl;b<=min(9,Zptr);b++)
{
Res=((long long)Res+b)%MOD;
}
}
}
//printf("%d %d::\n",d,Res-Use);
for(int sp=d+2;sp<=x/d;sp+=2)
{
int a=(d+sp)/2;
int b=(a-d);
if(a>n)
{
continue;
}
long long Ma=1;
long long Mb=1;
int k;
for(k=1;;k++)
{
Ma=Ma*a;
Mb=Mb*b;
if(Ma-Mb>x)
{
k--;
break;
}
}
for(int len=k;len>=1;len--)
{
Vis.clear();
long long Na=Ma;
long long Nb=Mb;
Vis[0]=1;
for(int i=len;i>=1;i--)
{
Na/=a;
Nb/=b;
Tmp.clear();
for(int j=(i==len);j<min(10,b);j++)
{
for(auto it=Vis.begin();it!=Vis.end();it++)
{
pair<int,int>Tty=(*it);
int Nro=(Tty.first+(Na-Nb)*j);
if(Nro>x)
{
continue;
}
Tmp[Nro]=((long long)Tmp[Nro]+Tty.second)%MOD;
}
}
Vis=Tmp;
}
Ma/=a;
Mb/=b;
Res=((long long)Res+((long long)Vis[x]*min(b,10))%MOD)%MOD;
}
}
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&x);
for(int d=1;d*d<=x;d++)
{
if(x%d==0)
{
work(d);
if(d*d!=x)
{
work(x/d);
}
}
}
printf("%d\n",Res);
//cerr<<(clock()*1.0/CLOCKS_PER_SEC)<<endl;
}
ABC287Ex
直接bitset优化floyd即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2005;
const int MAXQ=1e4+5;
int n,m,q;
int x,y;
pair<int,int> Q[MAXQ];
int Ans[MAXQ];
bitset<MAXN>S[MAXN];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
S[x].set(y);
}
for(int i=1;i<=n;i++)
{
S[i].set(i);
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d %d",&x,&y);
Q[i]=make_pair(x,y);
Ans[i]=-1;
if(S[Q[i].first][Q[i].second])
{
Ans[i]=0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(S[j][i])
{
S[j]|=S[i];
}
}
for(int j=1;j<=q;j++)
{
if(Ans[j]==-1)
{
if(S[Q[j].first][Q[j].second])
{
Ans[j]=i;
}
}
}
}
for(int i=1;i<=q;i++)
{
printf("%d\n",max(Ans[i],max(Q[i].first,Q[i].second)));
}
}
ABC286G
直接对非关键边缩点之后判欧拉回路即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
struct Edge{
int u,v;
}edge[MAXN];
int n,m,x,y;
int fa[MAXN];
int vis[MAXN];
int k;
int find(int x)
{
if(fa[x]==x)
{
return x;
}
fa[x]=find(fa[x]);
return fa[x];
}
void unionn(int i,int j)
{
fa[find(i)]=find(j);
}
int d[MAXN];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
edge[i]=((Edge){x,y});
}
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
scanf("%d",&x);
vis[x]=1;
}
for(int i=1;i<=m;i++)
{
if(!vis[i])
{
unionn(edge[i].u,edge[i].v);
}
}
for(int i=1;i<=m;i++)
{
if(vis[i])
{
d[find(edge[i].u)]++;
d[find(edge[i].v)]++;
}
}
int Cnt=0;
for(int i=1;i<=n;i++)
{
if(d[i]&1)
{
++Cnt;
}
}
if(Cnt==0||Cnt==2)
{
printf("Yes");
}
else{
printf("No");
}
}
ABC266G
傻瓜容斥(话说这种题我之前为啥没做出来
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=4e6+5;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int inv_fac[MAXN];
int fac[MAXN];
int C(int n,int m)
{
if(n<m||m<0)
{
return 0;
}
if(n==m||m==0)
{
return 1;
}
return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}
int k,R,G,B;
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
fac[0]=1;
for(int i=1;i<=MAXN-5;i++)
{
fac[i]=((long long)fac[i-1]*i)%MOD;
}
inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
for(int i=MAXN-5-1;i>=1;i--)
{
inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
}
scanf("%d %d %d %d",&R,&G,&B,&k);
int Res=0;
int n=R+G+B;
for(int i=k;i<=min(R,G);i++)
{
int val=C(n-i,i);
val=((long long)val*C(n-2*i,B))%MOD;
val=((long long)val*C(n-2*i-B,R-i))%MOD;
val=((long long)val*C(n-2*i-B-(R-i),G-i))%MOD;
val=((long long)val*C(i,k))%MOD;
if((i-k)&1)
{
Res=((long long)Res-val+MOD)%MOD;
}
else
{
Res=((long long)Res+val)%MOD;
}
}
printf("%d\n",Res);
}
ABC286Ex
不难想到最短路,连边要求不穿过凸包
实际上这个判断条件就是看凸包,不如直接在凸包上走
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
struct node{
double x,y;
node(double xx=0,double yy=0){
x=xx;
y=yy;
return;
}
node operator+(const node a)const{
return ((node){x+a.x,y+a.y});
}
node operator-(const node a)const{
return ((node){x-a.x,y-a.y});
}
};
double dist(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmpx(node a,node b)
{
if(a.x==b.x)
{
return a.y<b.y;
}
return a.x<b.x;
}
double cross(node a,node b)
{
return a.x*b.y-a.y*b.x;
}
int st[MAXN];
int head=0;
int Used[MAXN];
vector<node> Convex(vector<node>P)
{
for(int i=0;i<P.size();i++)
{
Used[i]=0;
}
sort(P.begin(),P.end(),cmpx);
head=0;
st[++head]=0;
for(int i=1;i<P.size();i++)
{
while(head>=2&&cross(P[st[head]]-P[st[head-1]],P[i]-P[st[head]])<=0)
{
Used[st[head]]=0;
head--;
}
st[++head]=i;
Used[i]=1;
}
int Mp=head;
for(int i=P.size()-1;i>=0;i--)
{
if(Used[i])
{
continue;
}
while(head>Mp&&cross(P[st[head]]-P[st[head-1]],P[i]-P[st[head]])<=0)
{
Used[st[head]]=0;
head--;
}
st[++head]=i;
Used[i]=1;
}
vector<node>R;
R.clear();
for(int i=1;i<head;i++)
{
R.push_back(P[st[i]]);
}
return R;
}
vector<node>V;
int n;
double x,y;
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf %lf",&x,&y);
V.push_back((node){x,y});
}
double sx,sy,tx,ty;
scanf("%lf %lf",&x,&y);
V.push_back((node){x,y});
sx=x;
sy=y;
scanf("%lf %lf",&x,&y);
V.push_back((node){x,y});
tx=x;
ty=y;
V=Convex(V);
int s=-1,t=-1;
for(int i=0;i<V.size();i++)
{
if(V[i].x==sx&&V[i].y==sy)
{
s=i;
}
if(V[i].x==tx&&V[i].y==ty)
{
t=i;
}
}
if(s==-1||t==-1)
{
printf("%lf",dist((node){sx,sy},(node){tx,ty}));
return 0;
}
double Res=2e18;
if(s>t)
{
swap(s,t);
}
double Tot=0;
for(int i=s;i<t;i++)
{
Tot+=dist(V[i],V[i+1]);
}
Res=Tot;
Tot=0;
for(int i=t;i<V.size()-1;i++)
{
Tot+=dist(V[i],V[i+1]);
}
Tot+=dist(V.back(),V[0]);
for(int i=0;i<s;i++)
{
Tot+=dist(V[i],V[i+1]);
}
Res=min(Res,Tot);
printf("%.9lf",Res);
}
ABC285G
把网格图抽象为二分图后不难看出上下界网络流
Show Code
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int MAXN=305*305;
const int MAXM=305*305*4;
struct Edge{
int to,val,nex;
}edge[MAXM*4];
int cnt_edge=1;
int head[MAXN];
int arc[MAXN];
int dis[MAXN];
void Add(int u,int v,int val)
{
edge[++cnt_edge].nex=head[u];
edge[cnt_edge].to=v;
edge[cnt_edge].val=val;
head[u]=cnt_edge;
}
void add(int u,int v,int val)
{
Add(u,v,val);
Add(v,u,0);
return;
}
int s,t;
int bfs()
{
memset(dis,-1,sizeof(dis));
dis[s]=0;
queue<int>q;
q.push(s);
arc[s]=head[s];
while(q.size())
{
int temp=q.front();
q.pop();
for(int i=head[temp];i;i=edge[i].nex)
{
int v=edge[i].to;
int w=edge[i].val;
if(w>0&&dis[v]==-1)
{
arc[v]=head[v];
dis[v]=dis[temp]+1;
q.push(v);
}
}
}
return (dis[t]==-1)?0:1;
}
int dfs(int x,int Lit)
{
if(x==t)
{
return Lit;
}
int used=0;
int rest=Lit;
for(int i=arc[x];i;i=edge[i].nex)
{
arc[x]=i;
int v=edge[i].to;
int w=edge[i].val;
if(dis[v]==dis[x]+1&&w>0)
{
int Nowx=dfs(v,min(w,rest));
if(!Nowx)
{
continue;
}
used+=Nowx;
rest-=Nowx;
edge[i].val-=Nowx;
edge[i^1].val+=Nowx;
if(used==Lit)
{
break;
}
}
}
return used;
}
int dinic()
{
int Maxflow=0;
while(bfs())
{
int flow;
while((flow=dfs(s,INF)))
{
Maxflow+=flow;
}
}
return Maxflow;
}
int n,m;
char mp[305][305];
vector<pair<int,pair<int,int> > >g[MAXN];
int M[MAXN];
int zfx[4]={0,0,1,-1};
int zfy[4]={1,-1,0,0};
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
}
int S=0;
int T=(n*m+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if((i+j)%2==0)
{
if(mp[i][j]=='2')
{
g[S].push_back(make_pair((i-1)*m+j,make_pair(1,1)));
}
else if(mp[i][j]=='?')
{
g[S].push_back(make_pair((i-1)*m+j,make_pair(0,1)));
}
for(int k=0;k<4;k++)
{
int nx=i+zfx[k];
int ny=j+zfy[k];
if(nx>=1&&ny>=1&&nx<=n&&ny<=m)
{
if(mp[nx][ny]=='?'||mp[nx][ny]=='2')
{
g[(i-1)*m+j].push_back(make_pair((nx-1)*m+ny,make_pair(0,1)));
}
}
}
}
else
{
if(mp[i][j]=='2')
{
g[(i-1)*m+j].push_back(make_pair(T,make_pair(1,1)));
}
else if(mp[i][j]=='?')
{
g[(i-1)*m+j].push_back(make_pair(T,make_pair(0,1)));
}
}
}
}
s=n*m+2;
t=n*m+3;
for(int i=0;i<=n*m+1;i++)
{
for(int j=0;j<g[i].size();j++)
{
int v=g[i][j].first;
int L=g[i][j].second.first;
int R=g[i][j].second.second;
M[v]+=L;
M[i]-=L;
add(i,v,R-L);
}
}
int Tot=0;
add(T,S,INF);
for(int i=0;i<=n*m+1;i++)
{
if(M[i]>0)
{
Tot+=M[i];
add(s,i,M[i]);
}
else if(M[i]<0)
{
add(i,t,-M[i]);
}
}
//printf("%d %d\n",Tot,dinic());
if(Tot==dinic())
{
printf("Yes");
}
else
{
printf("No");
}
}
ABC284G
呕心的推狮子
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,M;
int f[MAXN];
int P[MAXN];
int A(int n,int m)
{
if(m>n)
{
return 0;
}
int Res=1;
for(int i=n-m+1;i<=n;i++)
{
Res=((long long)Res*i)%M;
}
return Res;
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&M);
P[0]=1;
for(int i=1;i<=n;i++)
{
P[i]=((long long)P[i-1]*n)%M;
}
f[n]=0;
for(int i=n;i>=2;i--)
{
int Val=1;
Val=((long long)Val*P[n-i])%M;
Val=((long long)Val+(((long long)n-i)*f[i])%M)%M;
f[i-1]=Val;
}
int C=1;
int Res=0;
for(int i=1;i<n;i++)
{
C=((long long)C*(n-i))%M;
int V=((long long)C*i)%M;
V=((long)V*f[i])%M;
Res=((long long)Res+V)%M;
}
Res=((long long)Res*n)%M;
printf("%d\n",Res);
// Res=0;
// for(int d=1;d<n;d++)
// {
// int t=0;
// for(int s=1;s<=n;s++)
// {
// if(n-d-s>=0)
// {
// t=((long long)t+((long long)P[n-d-s]*A(n-d-1,s-1))%M)%M;
// }
// }
// t=((long long)t*d)%M;
// t=((long long)t*A(n-1,d))%M;
// Res=((long long)Res+t)%M;
// }
// Res=((long long)Res*n)%M;
// printf("%d\n",Res);
}
ABC257G
zz KMP 没啥好说得
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+5;
string s,t;
int nxt[MAXN];
int Cop[MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
cin>>s;
cin>>t;
nxt[0]=-1;
int i=0;
int j=-1;
while(i<s.size())
{
if(j==-1||(s[i]==s[j]))
{
i++;
j++;
nxt[i]=j;
}
else
{
j=nxt[j];
}
}
// cerr<<"fuck"<<endl;
i=0;
j=0;
while(i<t.size())
{
if(j==-1||(t[i]==s[j]))
{
i++;
j++;
//printf("%d %d\n",i,j);
Cop[i]=j;
if(j==s.size())
{
j=nxt[j];
}
}
else
{
j=nxt[j];
}
}
int Now=t.size();
int Res=0;
while(Now>=1)
{
Res++;
int Len=Cop[Now];
if(Len==0||Len==-1)
{
printf("-1");
return 0;
}
Now-=Len;
}
if(Now!=0)
{
printf("-1");
}
else
{
printf("%d\n",Res);
}
}
ABC283G
线性基半屉
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
long long l,r;
int n;
long long a[MAXN];
long long B[61];
int zero;
void Insert(long long x)
{
for(int i=60;i>=0;i--)
{
if((x>>i)&1)
{
if(B[i])
{
x^=B[i];
}
else
{
B[i]=x;
break;
}
}
}
if(!x)
{
zero=1;
}
}
long long Reuse[65];
long long d[65];
int cnt=0;
void rebuild()
{
for(int i=60;i>=0;i--)
{
d[i]=B[i];
}
cnt=0;
for(int i=60;i>=0;i--)
{
for(int j=i-1;j>=0;j--)
{
if((d[i]>>j)&1)
{
d[i]^=d[j];
}
}
}
for(int i=0;i<=60;i++)
{
if(d[i])
{
// printf("%d %lld\n",i,d[i]);
Reuse[++cnt]=d[i];
}
}
return;
}
long long Query_rank(long long x)
{
rebuild();
long long Res=0;
for(int i=cnt;i>=1;i--)//高位先筛
{
if(x>=Reuse[i])//不会出现1000被0100筛的情况
{
Res+=(1<<((i-1)));
//
x^=Reuse[i];
}
}
return Res;
}
long long Query_rankval(int k)
{
if(1)
{
k-=1;
}
if(k>=(1ll<<(cnt)))
{
return -1;
}
long long Res=0;
for(int i=60;i>=0;i--)
{
if((k>>i)&1ll)
{
Res^=(Reuse[i+1]);
}
}
return Res;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %lld %lld",&n,&l,&r);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
Insert(a[i]);
}
rebuild();
for(long long i=l;i<=r;i++)
{
printf("%lld ",Query_rankval(i));
}
}
ABC324G
主席树板子
Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=2e5+5;
struct Seg{
int date;
int lc,rc;
}Tree[MAXN*40];
int rt[MAXN];
int cnt_node;
int copy(int p)
{
Tree[++cnt_node]=Tree[p];
return cnt_node;
}
void Insert(int &p,int o,int l,int r,int k,int x)
{
p=copy(o);
Tree[p].date+=x;
if(l==r)
{
return;
}
int mid=(l+r)>>1;
if(k<=mid)
{
Insert(ls,Tree[o].lc,l,mid,k,x);
}
else
{
Insert(rs,Tree[o].rc,mid+1,r,k,x);
}
}
int Query(int p,int l,int r,int ql,int qr)
{
if(l>r)
{
return 0;
}
if(l>=ql&&r<=qr)
{
return Tree[p].date;
}
int mid=(l+r)>>1;
int Res=0;
if(ql<=mid)
{
Res+=Query(ls,l,mid,ql,qr);
}
if(qr>mid)
{
Res+=Query(rs,mid+1,r,ql,qr);
}
return Res;
}
int n;
int a[MAXN];
int q;
struct node{
int l,r,lv,rv;
}s[MAXN];
int op,x,y;
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
Insert(rt[i],rt[i-1],1,n,a[i],1);
}
s[0]=((node){1,n,1,n});
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d %d %d",&op,&x,&y);
if(op==1)
{
if(s[x].l==-1)
{
s[i].l=-1;
printf("%d\n",0);
continue;
}
int l=s[x].l;
int r=s[x].r;
int Key=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(Query(rt[mid],1,n,s[x].lv,s[x].rv)-Query(rt[s[x].l-1],1,n,s[x].lv,s[x].rv)<=y)
{
l=mid+1;
Key=mid;
}
else
{
r=mid-1;
}
}
if(Key!=-1)
{
s[i]=s[x];
s[i].r=s[x].r;
s[x].r=Key;
s[i].l=Key+1;
printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
}
else
{
s[i]=s[x];
s[x].l=-1;
printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
}
}
else
{
if(s[x].l==-1)
{
s[i].l=-1;
printf("0\n");
}
else
{
if(s[x].lv<=y&&s[x].rv>y)
{
s[i]=s[x];
s[i].lv=y+1;
s[i].rv=s[x].rv;
s[x].rv=y;
printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
}
else if(y>=s[x].rv)
{
s[i].l=-1;
printf("0\n");
}
else
{
s[i]=s[x];
s[x].l=-1;
printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
}
}
}
}
}
ABC245H
好题
首先考虑\(M\)为质数的情况,抛开\(k=0\),显然\(a_i(i\in[1,n-1])\)确定了\(a_n\)也即唯一确定
如果\(M=p^k\),\(k=r\times p^d\)考虑先分配\(d\)个\(p\)到\(n\)个数中,方案为\(\binom{n-d+1}{d}\),然后再对其他数填上与\(p\)互质的数共\((M-\frac{M}{p})\)种
不过如果考虑\(k=0\)的情况,我们考虑容斥,减去不和法的,也即枚举\(d\),和上面的式子差不多,不过最后一项不确定,我们要乘上\(r\)的个数即\(\phi(p^{k-d})\)
如果都不是,考虑拆成若干个\(p^k\)的乘积,答案即为答案乘起来
Show Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=998244353;//
int Pow(int a,int b,int p)
{
a%=p;///
int res=1;
int base=a;
while(b)
{
if(b&1)
{///
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int n,m,k;
int C(int n,int m)
{
int res=1;
for(int i=n-m+1;i<=n;i++)
{
res=((long long)res*i)%MOD;
}
int Mp=1;
for(int i=1;i<=m;i++)///
{
Mp=((long long)Mp*i)%MOD;
}
Mp=inv(Mp,MOD);
return ((long long)res*Mp)%MOD;
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%lld %lld %lld",&k,&n,&m);
int Res=1;
for(int i=2;i<=m/i;i++)
{
if(m%i==0)
{
int q=0;
int Mul=1;
while(m%i==0)
{
m/=i;
q++;
Mul*=i;
}
if(n%Mul)
{
int d=0;
while(n%i==0)
{
d++;
n/=i;
}
int res=C(d+k-1,d);
res=((long long)res*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
Res=((long long)Res*res)%MOD;
}
else
{
int res=Pow(Mul,k,MOD);
int Mf=Mul;
for(int d=0;d<q;d++)
{
int rv=C(d+k-1,d);
rv=((long long)rv*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
rv=((long long)rv*((Mf-Mf/i)%MOD))%MOD;
res=((long long)res-rv+MOD)%MOD;
Mf/=i;
}
Res=((long long)Res*res)%MOD;
}
}
}
if(m>1)
{
int i=m;
int q=0;
int Mul=1;
while(m%i==0)
{
m/=i;
q++;
Mul*=i;
}
if(n%Mul)
{
int d=0;
while(n%i==0)
{
d++;
n/=i;
}
int res=C(d+k-1,d);
res=((long long)res*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
Res=((long long)Res*res)%MOD;
}
else
{
int res=Pow(Mul,k,MOD);
int Mf=Mul;
for(int d=0;d<q;d++)
{
int rv=C(d+k-1,d);
rv=((long long)rv*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
rv=((long long)rv*((Mf-Mf/i)%MOD))%MOD;
res=((long long)res-rv+MOD)%MOD;
Mf/=i;
}
Res=((long long)Res*res)%MOD;
}
}
printf("%d\n",Res);
}
ABC282G
经典\(trick\)??
这种比大小可以记录前\(i\)维最后一位的排名
转移前缀和优化一下
Show Code
#include<bits/stdc++.h>
#define y1 djnb
#define y2 wpyy
#define x1 jjet
#define x2 ygokg
using namespace std;
const int MAXN=105;
int n,K,MOD;
int dp[2][MAXN][MAXN][MAXN];
int sum00[2][MAXN][MAXN][MAXN];
int Query(int i,int p,int x1,int x2,int y1,int y2)
{
return ((((long long)sum00[i][x2][y2][p]-sum00[i][x2][y1-1][p]+MOD)%MOD-sum00[i][x1-1][y2][p]+MOD)%MOD+sum00[i][x1-1][y1-1][p])%MOD;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d %d",&n,&K,&MOD);
dp[1][1][1][0]=1;
for(int p=0;p<=n;p++)
{
for(int j=0;j<=n;j++)
{
for(int k=0;k<=n;k++)
{
sum00[1][j][k][p]=dp[1][j][k][p];
}
}
for(int j=0;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
sum00[1][j][k][p]=((long long)sum00[1][j][k][p]+sum00[1][j][k-1][p])%MOD;
}
}
for(int k=0;k<=n;k++)
{
for(int j=1;j<=n;j++)
{
sum00[1][j][k][p]=((long long)sum00[1][j][k][p]+sum00[1][j-1][k][p])%MOD;
}
}
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
for(int k=1;k<=i;k++)
{
for(int p=0;p<=i;p++)
{
dp[i&1][j][k][p]=((long long)Query((i&1)^1,p,1,j-1,k,n)+Query((i&1)^1,p,j,n,1,k-1))%MOD;
if(p)
{
dp[i&1][j][k][p]=((long long)dp[i&1][j][k][p]+Query((i&1)^1,p-1,1,j-1,1,k-1))%MOD;
dp[i&1][j][k][p]=((long long)dp[i&1][j][k][p]+Query((i&1)^1,p-1,j,n,k,n))%MOD;
}
}
}
}
for(int p=0;p<=n;p++)
{
for(int j=0;j<=n;j++)
{
for(int k=0;k<=n;k++)
{
sum00[i&1][j][k][p]=dp[i&1][j][k][p];
}
}
for(int j=0;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
sum00[i&1][j][k][p]=((long long)sum00[i&1][j][k][p]+sum00[i&1][j][k-1][p])%MOD;
}
}
for(int k=0;k<=n;k++)
{
for(int j=1;j<=n;j++)
{
sum00[i&1][j][k][p]=((long long)sum00[i&1][j][k][p]+sum00[i&1][j-1][k][p])%MOD;
}
}
}
}
int Res=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
Res=((long long)Res+dp[n&1][i][j][K])%MOD;
}
}
printf("%d\n",Res);
}
ABC275Ex
不难看出笛卡尔树
不难直接列出一个暴力\(dp\),\(dp_{u,x}=\min dp_{v,t}+tB_u-xB_u,t\ge \max A_u,x\)
发现\((t)B_u\)是个一次函数,我们大胆猜测这是个凸函数
直接用左偏树维护二阶导即可,你只需实现前缀删\(<A_u\)及斜率\(<0\)的
这个删\(A_u\)不好搞,把它也插进去即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int n;
int A[MAXN];
int B[MAXN];
int ls[MAXN];
int rs[MAXN];
int st[MAXN];
int head;
struct Heap_node{
int valx,lc,rc;
int valk;
int dist;
}Tree[MAXN*4];
int cnt_node;
int New(int x,int k)
{
++cnt_node;
Tree[cnt_node].dist=Tree[cnt_node].rc=Tree[cnt_node].lc=0;
Tree[cnt_node].valx=x;
Tree[cnt_node].valk=k;
return cnt_node;
}
int Merge(int x,int y)
{
if((!x)||(!y))
{
return x+y;
}
if(Tree[x].valx>Tree[y].valx)
{
swap(x,y);
}
Tree[x].rc=Merge(Tree[x].rc,y);
if(Tree[Tree[x].lc].dist<Tree[Tree[x].rc].dist)
{
swap(Tree[x].lc,Tree[x].rc);
}
Tree[x].dist=Tree[Tree[x].rc].dist+1;
return x;
}
int Pop(int x)
{
return Merge(Tree[x].lc,Tree[x].rc);
}
int rt[MAXN];
void Print(int x)
{
vector<pair<int,int> >Used;
while(rt[x])
{
pair<int,int> Use=make_pair(Tree[rt[x]].valx,Tree[rt[x]].valk);
rt[x]=Pop(rt[x]);
Used.push_back(Use);
printf("%d %d\n",Use.first,Use.second);
}
for(int i=0;i<Used.size();i++)
{
rt[x]=Merge(rt[x],New(Used[i].first,Used[i].second));
}
}
void dfs(int x)
{
if(ls[x])
{
dfs(ls[x]);
}
if(rs[x])
{
dfs(rs[x]);
}
if((!ls[x])&&(!rs[x]))
{
rt[x]=Merge(New(0,-B[x]),New(A[x],B[x]));
return;
}
rt[x]=Merge(rt[ls[x]],rt[rs[x]]);
rt[x]=Merge(rt[x],New(0,B[x]));
rt[x]=Merge(rt[x],New(A[x],0));
int lh=0;
while(rt[x]&&(lh+Tree[rt[x]].valk<0||(Tree[rt[x]].valx<A[x])))
{
lh+=Tree[rt[x]].valk;
rt[x]=Pop(rt[x]);
}
rt[x]=Merge(New(Tree[rt[x]].valx,lh),rt[x]);
rt[x]=Merge(rt[x],New(0,-B[x]));
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&A[i]);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&B[i]);
}
for(int i=1;i<=n;i++)
{
while(head&&B[st[head]]<B[i])
{
head--;
}
if(!head)
{
ls[i]=st[head+1];
}
else
{
ls[i]=rs[st[head]];
rs[st[head]]=i;
}
st[++head]=i;
}
dfs(st[1]);
long long Res=0;
int lk=Tree[rt[st[1]]].valk,lx=Tree[rt[st[1]]].valx;
rt[st[1]]=Pop(rt[st[1]]);
while(rt[st[1]])
{
int nk=Tree[rt[st[1]]].valk;
int nx=Tree[rt[st[1]]].valx;
Res+=((-(long long)lk)*(nx-lx));
// printf("%d %d %d??\n",lx,nx,lk);
lx=nx;
lk+=nk;
rt[st[1]]=Pop(rt[st[1]]);
}
printf("%lld\n",Res);
}
ABC276Ex
先把\(0\)去掉,实际上\(1,2\)之间就是个高斯消元
有\(0\)的话我们就把\(1,2\)不涉及得矩形全填\(0\)即可
Show Code
#include<bits/stdc++.h>
#define x1 djnb
#define y1 djnbnnb
#define x2 djdjnb
#define y2 DJDJNBNBNB
using namespace std;
const int MAXN=2005;
struct Query{
int x1,y1,x2,y2,val;
}query[MAXN];
int n,q;
map<pair<int,int>,int>Vis;
int id=0;
int Used=0;
struct Martix{
bitset<MAXN*4>v[MAXN];
void guess()
{
for(int r=1,c=1;r<=Used&&c<=id;r++,c++)
{
int Main=0;
for(int i=r;i<=Used;i++)
{
if(v[i][c])
{
Main=i;
break;
}
}
if(!Main)
{
r--;
continue;
}
swap(v[r],v[Main]);
for(int i=1;i<=Used;i++)
{
if(i==r)
{
continue;
}
if(v[i][c])
{
v[i]^=v[r];
}
}
}
}
}A;
pair<int,int>V[MAXN*MAXN];
int Sv[MAXN][MAXN];
int cf[MAXN][MAXN];
int a[MAXN][MAXN];
int Cz[MAXN][MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&q);
for(int i=1;i<=q;i++)
{
scanf("%d %d %d %d %d",&query[i].x1,&query[i].x2,&query[i].y1,&query[i].y2,&query[i].val);
if(query[i].val)
{
++Used;
cf[query[i].x1][query[i].y1]++;
cf[query[i].x1][query[i].y2+1]--;
cf[query[i].x2+1][query[i].y1]--;
cf[query[i].x2+1][query[i].y2+1]++;
if(!Vis[make_pair(query[i].x2,query[i].y2)])
{
Vis[make_pair(query[i].x2,query[i].y2)]=++id;
V[id]=make_pair(query[i].x2,query[i].y2);
}
A.v[Used].set(Vis[make_pair(query[i].x2,query[i].y2)]);
if(query[i].x1-1>=1)
{
if(!Vis[make_pair(query[i].x1-1,query[i].y2)])
{
Vis[make_pair(query[i].x1-1,query[i].y2)]=++id;
V[id]=make_pair(query[i].x1-1,query[i].y2);
}
A.v[Used].set(Vis[make_pair(query[i].x1-1,query[i].y2)]);
}
if(query[i].y1-1>=1)
{
if(!Vis[make_pair(query[i].x2,query[i].y1-1)])
{
Vis[make_pair(query[i].x2,query[i].y1-1)]=++id;
V[id]=make_pair(query[i].x2,query[i].y1-1);
}
A.v[Used].set(Vis[make_pair(query[i].x2,query[i].y1-1)]);
}
if(query[i].x1-1>=1&&query[i].y1-1>=1)
{
if(!Vis[make_pair(query[i].x1-1,query[i].y1-1)])
{
Vis[make_pair(query[i].x1-1,query[i].y1-1)]=++id;
V[id]=make_pair(query[i].x1-1,query[i].y1-1);
}
A.v[Used].set(Vis[make_pair(query[i].x1-1,query[i].y1-1)]);
}
}
}
int hk=0;
++id;
for(int i=1;i<=q;i++)
{
if(query[i].val)
{
++hk;
if(query[i].val==2)
{
A.v[hk].set(id);
}
}
}
// for(int i=1;i<=Used;i++)
// {
// for(int j=1;j<=id;j++)
// {
// printf("%d",(int)A.v[i][j]);
// }
// printf("\n");
// }
A.guess();
// printf("\n");
// for(int i=1;i<=Used;i++)
// {
// for(int j=1;j<=id;j++)
// {
// printf("%d",(int)A.v[i][j]);
// }
// printf("\n");
// }
for(int i=1;i<=Used;i++)
{
vector<int>Vrp;
for(int j=1;j<id;j++)
{
if(A.v[i][j])
{
Vrp.push_back(j);
}
}
if(A.v[i][id]&&(!Vrp.size()))
{
printf("No");
return 0;
}
else
{
if(Vrp.size())
{
Sv[V[Vrp[0]].first][V[Vrp[0]].second]=A.v[i][id];
for(int j=1;j<Vrp.size();j++)
{
Sv[V[Vrp[j]].first][V[Vrp[j]].second]=0;
}
}
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=n;j++)
// {
// printf("%d ",Sv[i][j]);
// }
// printf("\n");
// }
for(int i=n;i>=1;i--)
{
for(int j=n;j>=1;j--)
{
Sv[i][j]=Sv[i][j]^Sv[i-1][j]^Sv[i-1][j-1]^Sv[i][j-1];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cf[i][j]=cf[i][j]+cf[i-1][j]+cf[i][j-1]-cf[i-1][j-1];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(cf[i][j])
{
if(Sv[i][j])
{
a[i][j]=2;
}
else
{
a[i][j]=1;
}
}
else
{
a[i][j]=0;
}
Cz[i][j]=Cz[i-1][j]+Cz[i][j-1]-Cz[i-1][j-1]+(a[i][j]==0);
}
}
for(int i=1;i<=q;i++)
{
if(query[i].val==0)
{
if(Cz[query[i].x2][query[i].y2]-Cz[query[i].x2][query[i].y1-1]-Cz[query[i].x1-1][query[i].y2]+Cz[query[i].x1-1][query[i].y1-1])
{
}
else
{
printf("No");
return 0;
}
}
}
printf("Yes\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",a[i][j]);
}
printf("\n");
}
}
ABC277Ex
一眼\(2-SAT\)
如果\((i,j)\)表示\(=j\)是否可行似乎不好弄
直接让\((i,j)\)表示\(\ge j\)是否可行即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e6+5;
int n,m;
int q;
int a,b,l,r;
int Hash(int x,int y)
{
return (x-1)*(m+1)+(y+1);
}
int Hashr(int x,int y)
{
return (x-1)*(m+1)+(y+1)+(n*(m+1));
}
vector<int>g[MAXN];
int cnt_dfn;
int cnt_scc;
int dfn[MAXN];
int low[MAXN];
stack<int>st;
int scc[MAXN];
void dfs(int x)
{
dfn[x]=++cnt_dfn;
low[x]=dfn[x];
st.push(x);
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(dfn[v])
{
if(!scc[v])
{
low[x]=min(low[x],dfn[v]);
}
}
else
{
dfs(v);
low[x]=min(low[x],low[v]);
}
}
if(low[x]==dfn[x])
{
++cnt_scc;
while(st.size())
{
scc[st.top()]=cnt_scc;
if(st.top()==x)
{
st.pop();
break;
}
st.pop();
}
}
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d %d",&n,&m,&q);
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
if(j)
{
g[Hash(i,j)].push_back(Hash(i,j-1));
}
if(j!=m)
{
g[Hashr(i,j)].push_back(Hashr(i,j+1));
}
}
g[Hashr(i,0)].push_back(Hash(i,0));
}
for(int i=1;i<=q;i++)
{
scanf("%d %d %d %d",&a,&b,&l,&r);
for(int j=0;j<=m;j++)
{
int Nl=l-j;
int Nr=r-j;
if(Nr+1<=m&&Nr+1>=0)
{
g[Hash(a,j)].push_back(Hashr(b,Nr+1));
g[Hash(b,j)].push_back(Hashr(a,Nr+1));
}
else if(Nr+1<0)
{
g[Hash(a,j)].push_back(Hashr(a,j));
g[Hash(b,j)].push_back(Hashr(b,j));
}
if(Nl+1<=m&&Nl+1>=0)
{
g[Hashr(a,j)].push_back(Hash(b,Nl+1));
g[Hashr(b,j)].push_back(Hash(a,Nl+1));
}
else if(Nl+1>m)
{
g[Hashr(a,j)].push_back(Hash(a,j));
g[Hashr(b,j)].push_back(Hash(b,j));
}
}
}
for(int i=1;i<=2*n*(m+1);i++)
{
if(!dfn[i])
{
dfs(i);
}
}
// for(int i=1;i<=2*n*(m+1);i++)
// {
// for(int j=0;j<g[i].size();j++)
// {
// printf("%d %d\n",i,g[i][j]);
// }
// }
// printf("%d???\n",cnt_scc);
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
if(scc[Hash(i,j)]==scc[Hashr(i,j)])
{
printf("-1");
return 0;
}
}
}
for(int i=1;i<=n;i++)
{
int NYH=0;
for(int j=0;j<=m;j++)
{
if(scc[Hash(i,j)]<scc[Hashr(i,j)])
{
NYH=j;
}
else
{
break;
}
}
printf("%d ",NYH);
}
}
ABC281G
一眼分层然后\(dp\)
Show Code
#include<bits/stdc++.h>
using namespace std;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
const int MAXN=505;
int n,MOD;
int Pw[MAXN*MAXN];
int C[MAXN][MAXN];
int dp[MAXN][MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&MOD);
C[0][0]=1;
Pw[0]=1;
for(int i=0;i<=n;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++)
{
C[i][j]=((long long)C[i-1][j]+C[i-1][j-1])%MOD;
}
}
for(int i=1;i<=n*n;i++)
{
Pw[i]=((long long)Pw[i-1]*2)%MOD;
}
dp[1][1]=1;
for(int j=2;j<=n;j++)
{
for(int k=1;k<=j;k++)
{
for(int l=1;l<=n;l++)
{
int Rj=dp[j-k][l];
Rj=((long long)Rj*Pow(((long long)Pw[l]-1+MOD)%MOD,k,MOD))%MOD;
dp[j][k]=((long long)dp[j][k]+Rj)%MOD;
}
dp[j][k]=((long long)dp[j][k]*C[n-1-(j-k)][k])%MOD;
dp[j][k]=((long long)dp[j][k]*Pw[(k*(k-1))/2])%MOD;
}
}
int Res=0;
for(int k=1;k<=n;k++)
{
int tk=dp[n-1][k];
tk=((long long)tk*(Pw[k]-1)%MOD);
Res=((long long)Res+tk)%MOD;
}
printf("%d\n",Res);
}
ABC279G
男泵
设\(dp_{i,0/1}\)表示前\(k-1\)得状态就行了
阿哲,最开始想得前\(k\),后面被带偏了/kk
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=1e6+5;
int n,k,c;
int dp[MAXN][2];
int sum[MAXN][2];
int Get(int x,int op)
{
if(x<0)
{
return 0;
}
return sum[x][op];
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d %d",&n,&k,&c);
for(int i=1;i<=n;i++)
{
// for(int j=1;j<=(i-k)+1;j++)
// {
// dp[i][0]=((long long)dp[i][0]+(((long long)c-1)*dp[j][0]+dp[j][1])%MOD)%MOD;
// }
dp[i][0]=((long long)dp[i][0]+((long long)c-1)*(Get(i-k+1,0))%MOD)%MOD;
dp[i][0]=((long long)dp[i][0]+(Get(i-k+1,1)))%MOD;
dp[i][0]=((long long)dp[i][0]+c)%MOD;
// for(int j=i-k+2;j<=i-1;j++)
// {
// dp[i][1]=((long long)dp[i][1]+(((long long)c-1)*dp[j][0]+dp[j][1])%MOD)%MOD;
// }
dp[i][1]=((long long)dp[i][1]+((long long)c-1)*((Get(i-1,0)-Get(i-k+1,0)+MOD)%MOD)%MOD)%MOD;
dp[i][1]=((long long)dp[i][1]+((Get(i-1,1)-Get(i-k+1,1)+MOD)%MOD))%MOD;
sum[i][0]=((long long)sum[i-1][0]+dp[i][0])%MOD;
sum[i][1]=((long long)sum[i-1][1]+dp[i][1])%MOD;
}
printf("%d\n",((long long)dp[n][0]+dp[n][1])%MOD);
}
ABC278G
自闭了
\(l\not = r\)明显先手必胜
否则\(l=r\)直接\(sg\),输出方案得话就看\(sg=0\)得局面
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2005;
int n,l,r;
int a,b;
int dp[MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
cin>>n>>l>>r;
if(l==r)
{
for(int i=0;i<l;i++)
{
dp[i]=0;
}
for(int i=l;i<=n;i++)
{
vector<int>V;
for(int j=0;j<=i-l;j++)
{
V.push_back(dp[j]^dp[i-l-j]);
}
sort(V.begin(),V.end());
V.erase(unique(V.begin(),V.end()),V.end());
dp[i]=V.size();
for(int j=0;j<V.size();j++)
{
if(V[j]!=j)
{
dp[i]=j;
break;
}
}
}
if(dp[n])
{
cout<<"First"<<endl;
set<pair<int,int> >V;
V.insert(make_pair(1,n));
int Sum=dp[n];
pair<int,int>MRk;
for(auto it=V.begin();it!=V.end();it++)
{
pair<int,int>tmp=(*it);
int L=tmp.first;
int R=tmp.second;
int Ns=Sum^(dp[tmp.second-tmp.first+1]);
int Ki=-1;
for(int i=0;i<=(R-L+1)-l;i++)
{
if((Ns^dp[i]^dp[(R-L+1)-l-i])==0)
{
Ki=i;
break;
}
}
if(Ki!=-1)
{
cout<<Ki+L<<" "<<l<<endl;
MRk=(*it);
Sum=Ns;
if(L<=L+Ki-1)
{
V.insert(make_pair(L,L+Ki-1));
Sum^=dp[Ki];
}
if(Ki+L+l<=R)
{
V.insert(make_pair(Ki+L+l,R));
Sum^=dp[R-(Ki+L+l)+1];
}
break;
}
}
V.erase(MRk);
cin>>a>>b;
while((a)&&(a!=-1))
{
b=a+b-1;
auto it=V.upper_bound(make_pair(a,n+1));
--it;
Sum^=dp[(*it).second-(*it).first+1];
auto Tmp=(*it);
V.erase(it);
if(Tmp.first<a)
{
V.insert(make_pair(Tmp.first,a-1));
Sum^=dp[a-Tmp.first];
}
if(b+1<=Tmp.second)
{
V.insert(make_pair(b+1,Tmp.second));
Sum^=dp[Tmp.second-b];
}
pair<int,int>Mrk;
for(it=V.begin();it!=V.end();it++)
{
pair<int,int>tmp=(*it);
int L=tmp.first;
int R=tmp.second;
int Ns=Sum^(dp[tmp.second-tmp.first+1]);
int Ki=-1;
for(int i=0;i<=(R-L+1)-l;i++)
{
if((Ns^dp[i]^dp[(R-L+1)-l-i])==0)
{
Ki=i;
break;
}
}
if(Ki!=-1)
{
cout<<Ki+L<<" "<<l<<endl;
// cout<<a<<" "<<b<<endl;
Mrk=(*it);
Sum=Ns;
if(L<=L+Ki-1)
{
V.insert(make_pair(L,L+Ki-1));
Sum^=dp[Ki];
}
if(Ki+L+l<=R)
{
V.insert(make_pair(Ki+L+l,R));
Sum^=dp[R-(Ki+L+l)+1];
}
break;
}
}
V.erase(Mrk);
cin>>a>>b;
}
}
else
{
cout<<"Second"<<endl;
set<pair<int,int> >V;
V.insert(make_pair(1,n));
int Sum=dp[n];
cin>>a>>b;
while((a)&&(a!=-1))
{
b=a+b-1;
auto it=V.upper_bound(make_pair(a,n+1));
--it;
Sum^=dp[(*it).second-(*it).first+1];
auto Tmp=(*it);
V.erase(it);
if(Tmp.first<a)
{
V.insert(make_pair(Tmp.first,a-1));
Sum^=dp[a-Tmp.first];
}
if(b+1<=Tmp.second)
{
V.insert(make_pair(b+1,Tmp.second));
Sum^=dp[Tmp.second-b];
}
pair<int,int>Mrk;
for(it=V.begin();it!=V.end();it++)
{
pair<int,int>tmp=(*it);
int L=tmp.first;
int R=tmp.second;
int Ns=Sum^(dp[tmp.second-tmp.first+1]);
int Ki=-1;
for(int i=0;i<=(R-L+1)-l;i++)
{
if((Ns^dp[i]^dp[(R-L+1)-l-i])==0)
{
Ki=i;
break;
}
}
if(Ki!=-1)
{
cout<<Ki+L<<" "<<l<<endl;
// cout<<a<<" "<<b<<endl;
Mrk=(*it);
Sum=Ns;
if(L<=L+Ki-1)
{
V.insert(make_pair(L,L+Ki-1));
Sum^=dp[Ki];
}
if(Ki+L+l<=R)
{
V.insert(make_pair(Ki+L+l,R));
Sum^=dp[R-(Ki+L+l)+1];
}
break;
}
}
V.erase(Mrk);
cin>>a>>b;
}
}
}
else
{
cout<<"First"<<endl;
int Now=l;
if((n&1)!=(Now&1))
{
Now++;
}
int x=(n-Now)/2;
cout<<x+1<<" "<<Now<<endl;
cin>>a>>b;
while(a&&(a!=-1))
{
int L=a;
int R=a+b-1;
swap(L,R);
L=n-L+1;
R=n-R+1;
cout<<L<<" "<<R-L+1<<endl;
cin>>a>>b;
}
}
}
ABC277G
没看出来套路自闭了
考虑维护\(dp_{i,j,1/2}\)表示走到\(i\)用了\(j\)时当前\(x/x^2\)的期望
答案就是这些加起来
注意常数项也要算进去
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=3005;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int Inv[MAXN];
int n,m,k;
int x,y;
int c[MAXN];
vector<int>g[MAXN];
int dp[MAXN][MAXN][3];
int f[MAXN][MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&c[i]);
Inv[i]=inv(i,MOD);
}
f[1][0]=1;
dp[1][0][0]=0;
dp[1][0][1]=0;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
for(int p=0;p<(g[j].size());p++)
{
int v=g[j][p];
f[j][i]=((long long)f[j][i]+((long long)f[v][i-1]*Inv[g[v].size()])%MOD)%MOD;
if(!c[j])
{
dp[j][i][0]=((long long)dp[j][i][0]+((((long long)dp[v][i-1][0]+f[v][i-1])%MOD)*Inv[g[v].size()])%MOD)%MOD;
dp[j][i][1]=((long long)dp[j][i][1]+((((long long)dp[v][i-1][1]+2ll*dp[v][i-1][0]+f[v][i-1])%MOD)*Inv[g[v].size()])%MOD)%MOD;
}
else
{
dp[j][i][0]=((long long)dp[j][i][0]+(((long long)dp[v][i-1][0])*Inv[g[v].size()])%MOD)%MOD;
dp[j][i][1]=((long long)dp[j][i][1]+(((long long)dp[v][i-1][1])*Inv[g[v].size()])%MOD)%MOD;
}
}
}
}
int Res=0;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
if(c[j])
{
int tot=dp[j][i][1];
Res=((long long)Res+tot)%MOD;
}
}
}
printf("%d\n",Res);
}
ABC276G
\(\sum\limits_{i=0}^{n-1}(-1)^i\binom{n-1}{i}\sum\limits_{j=i}^m\binom{m-2j+n}{n-1}\binom{j-1}{i-1}\)
算了,换个思路
差分一下,得到\(b\)
要求即使\(b_i\not \equiv0 \bmod 3\)且\(\sum b_i\le M\)
不考虑\(b_i\not \equiv 0 \bmod 3\),方案数为\(\binom{n+M-1}{M}\)
先全部\(\bmod 3\),那就只能填\(1,2\)
枚举和为\(m\)
则方案数为\(\sum\limits_{m=n-1}\binom{n-1}{m-(n-1)} \sum\limits_{l=0,m+3l\le M}\binom{l+n-2}{l}\)
第一个好像要枚举\(\bmod 3\)是多少吧
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=2e7+5;
int n,m;
int fac[MAXN];
int inv_fac[MAXN];
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int C(int n,int m)
{
if(n<m||m<0)
{
return 0;
}
if(n==m||m==0)
{
return 1;
}
return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}
int f[MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
fac[0]=1;
for(int i=1;i<=MAXN-5;i++)
{
fac[i]=((long long)fac[i-1]*i)%MOD;
}
inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
for(int i=MAXN-5-1;i>=1;i--)
{
inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
}
scanf("%d %d",&n,&m);
f[0]=1;
for(int i=1;i<=m;i++)
{
f[i]=((long long)f[i-1]+C(i+n-1,i))%MOD;
}
int Res=0;
for(int k=0;k<=2;k++)
{
for(int i=n-1;i<=2*(n-1);i++)
{
int vl=C(n-1,(i-(n-1)));
int Ct=(m-i-k)/3;
if(m-i-k>=0)
{
vl=((long long)vl*f[Ct])%MOD;
Res=((long long)Res+vl)%MOD;
//printf("%d %d %d::\n",k,i,vl);
}
}
}
printf("%d\n",Res);
}
ABC275G
首先转化一下无限那个条件
这个就相当于我们的物品可以取实数个
这样我们可以把所有物品的价值先定为\(1\),代价为\(\dfrac{a_i}{c_i}\)和\(\dfrac{b_i}{c_i}\)
答案即为\(\dfrac{\sum x_i}{\max(\sum a_ix_i,\sum b_ix_i)}\)
不妨取\(\sum x_i=1\),我们即要\(max(\sum a_ix_i,\sum b_ix_i)\)最小
二分这玩意为\(mid\),则\(max(\sum a_ix_i,\sum b_ix_i)\le mid\)
我们再把代价改为\(a_i-mid\)
然后就是\(\sum a_ix_i\le 0\& \sum b_ix_i\le 0\)
若\(a_i<0,b_i<0\)一定满足
否则我们可以只考虑\(a_i>0,b_i<0\)和\(a_i<0,b_i>0\)
我们可以把它再变换个形式\((\dfrac{-a_i}{b_i},-1)\)和\((-1,\dfrac{b_i}{-a_i})\),我们就要取最小的那个
令\(A=\dfrac{-a_i}{b_i},B=\dfrac{b_i}{-a_i}\)
即是否存在\(xA+x-1\le 0\)且\(-x+(1-x)B \le 0\)
则\(x\le \dfrac{1}{A+1}\)且\(\dfrac{B}{B+1}\le x\)
则\(\dfrac{B}{B+1}\le \dfrac{1}{A+1}\),\(AB\le 1\)
Show Code
#include<bits/stdc++.h>
#define eps 1e-7
using namespace std;
const int MAXN=2e5+5;
int n;
int a[MAXN];
int b[MAXN];
int c[MAXN];
long double A[MAXN];
long double B[MAXN];
bool check(long double mid)
{
long double Ap=0x3f3f3f3f,Bp=0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
A[i]=(a[i]*1.0/c[i])-mid;
B[i]=(b[i]*1.0/c[i])-mid;
if(A[i]>=0&&B[i]>=0)
{
continue;
}
if(A[i]<=0&&B[i]<=0)
{
return 1;
}
if(A[i]<0)
{
Bp=min(Bp,(-B[i]/A[i]));
}
else
{
Ap=min(Ap,(-A[i])/B[i]);
}
}
return (Ap*Bp<=1);
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d %d %d",&a[i],&b[i],&c[i]);
}
long double l=0;
long double r=1e18;
while(r-l>eps)
{
long double mid=(l+r)*1.0/2;
if(check(mid))
{
r=mid;
}
else
{
l=mid;
}
}
l=(1.0/l);
printf("%.9LF",l);
}
ABC274G
调了半天结果数组开小了
现在精神不大正常
最开始题看错了,看清楚后发现是覆盖一整行或列果断最小点覆盖
Show Code
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int MAXN=405;
int n,m;
char s[MAXN][MAXN];
int Idr,Idc;
int c[MAXN][MAXN];
int r[MAXN][MAXN];
struct Edge{
int nxt,to,val;
}edge[MAXN*MAXN*8];
int head[MAXN*MAXN];
int cnt_edge=1;
void Add(int u,int v,int val)
{
++cnt_edge;
edge[cnt_edge].nxt=head[u];
edge[cnt_edge].val=val;
edge[cnt_edge].to=v;
head[u]=cnt_edge;
return;
}
void add(int u,int v,int val)
{
Add(u,v,val);
Add(v,u,0);
}
int S,T;
int dis[MAXN*MAXN];
int arc[MAXN*MAXN];
int bfs()
{
memset(dis,-1,sizeof(dis));
queue<int>q;
q.push(S);
dis[S]=0;
while(q.size())
{
int u=q.front();
q.pop();
arc[u]=head[u];
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
int w=edge[i].val;
if(!w)
{
continue;
}
if(dis[v]!=-1)
{
continue;
}
dis[v]=dis[u]+1;
q.push(v);
}
}
return dis[T]!=-1;
}
int dfs(int x,int Cap)
{
if(x==T)
{
return Cap;
}
int Used=0;
for(int i=arc[x];i;i=edge[i].nxt)
{
arc[x]=i;
int v=edge[i].to;
int w=edge[i].val;
if(dis[v]==dis[x]+1)
{
if(!w)
{
continue;
}
int Flow=dfs(v,min(Cap,w));
edge[i].val-=Flow;
edge[i^1].val+=Flow;
Used+=Flow;
Cap-=Flow;
if(!Cap)
{
return Used;
}
}
}
return Used;
}
int dinic()
{
int Maxflow=0;
while(bfs())
{
int Flow;
while((Flow=dfs(S,INF)))
{
Maxflow+=Flow;
}
// cerr<<Maxflow<<endl;
}
return Maxflow;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
}
for(int i=1;i<=n;i++)
{
int las=1;
s[i][m+1]='#';
for(int j=1;j<=m+1;j++)
{
if(s[i][j]=='#')
{
if(las<=j-1)
{
++Idr;
for(int k=las;k<=j-1;k++)
{
r[i][k]=Idr;
}
}
las=j+1;
}
}
}
for(int i=1;i<=m;i++)
{
int las=1;
s[n+1][i]='#';
for(int j=1;j<=n+1;j++)
{
if(s[j][i]=='#')
{
if(las<=j-1)
{
++Idc;
for(int k=las;k<=j-1;k++)
{
c[k][i]=Idc;
}
}
las=j+1;
}
}
}
S=0;
T=Idc+Idr+1;
for(int i=1;i<=Idr;i++)
{
add(S,i,1);
}
for(int i=1;i<=Idc;i++)
{
add(i+Idr,T,1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='.')
{
add(r[i][j],c[i][j]+Idr,1);
}
}
}
printf("%d\n",dinic());
}
ABC220Ex
感觉很像\(2^{\frac{n}{2}}\),不过完全没思路
直接令\(S\)为前\(\dfrac{n}{2}\)个点组成点集
设\(f_1(s)\)为选\(s\)的边的奇偶,\(s\sube S\),\(f_2(t)\)为选\(t\)且只有\(t\)的边
我们可以发现边就是由\(f_1(s)\oplus f_2(t)\)再算上分别连在\(S/s,t\)的边组成
对于分别连在\(s,t\)的边,我们考虑先处理出\(g(s)\)表示在\(T\)中与\(s\)有奇数条边相连的点集
那么答案即是\(\sum[f_1(s)\oplus f_2(s)\oplus(popcount(g(s)\&t) \& 1\ )=0]\)
枚举\(popcount(g(s)\&t)\),即\(\sum\limits_{p=0}\sum\limits_{popcount(g(s)\& t)=p}[f_1(s)\oplus f_2(t)\oplus(p\&1)=0]\)
考虑计算\(\sum\limits_{p=0}\sum\limits_{g(s)\& t=p}[f_1(s)\oplus f_2(t)=0/1]\),这看着很与卷积
枚举\(g(s)\)取值时\(f_1(s)=0/1\)的方案数即可
Show Code
#include<bits/stdc++.h>
using namespace std;
int N;
int m;
int x,y;
vector<int>g[45];
int f1[(1<<20)+5];
int f2[(1<<20)+5];
int f[(1<<20)+5];
long long c1[2][(1<<20)+5];
long long c2[2][(1<<20)+5];
long long h[2][(1<<20)+5];
int n1,n2;
void FWT(long long *a)
{
for(int len=2;len<=(1<<n2);len<<=1)
{
for(int i=0;i<(1<<n2);i+=len)
{
for(int j=i;j<i+(len>>1);j++)
{
long long tmp1=a[j];
long long tmp2=a[j+(len>>1)];
a[j]=tmp1+tmp2;
a[j+(len>>1)]=tmp2;
}
}
}
}
void IFWT(long long *a)
{
for(int len=2;len<=(1<<n2);len<<=1)
{
for(int i=0;i<(1<<n2);i+=len)
{
for(int j=i;j<i+(len>>1);j++)
{
long long tmp1=a[j];
long long tmp2=a[j+(len>>1)];
a[j]=tmp1-tmp2;
a[j+(len>>1)]=tmp2;
}
}
}
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&N,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
x--;
y--;
g[x].push_back(y);
g[y].push_back(x);
}
n1=(N/2);
n2=N-(N/2);
for(int i=1;i<(1<<n1);i++)
{
int lob=__builtin_ctz(i);
int ret=(i^(1<<lob));
f1[i]=f1[ret];
f[i]=f[ret];
for(int j=0;j<g[lob].size();j++)
{
int v=g[lob][j];
if(((!((ret>>(v))&1))&&(v<n1))||(v>=n1))
{
f1[i]^=1;
}
if(v>=n1)
{
f[i]^=(1<<(v-n1));
}
}
// printf("%d %d %d---\n",i,f1[i],f[i]);
}
for(int i=1;i<(1<<n2);i++)
{
int lob=__builtin_ctz(i);
int ret=(i^(1<<lob));
f2[i]=f2[ret];
for(int j=0;j<g[lob+n1].size();j++)
{
int v=g[lob+n1][j];
if((v>=n1)&&(!((ret>>((v-n1)))&1)))
{
f2[i]^=1;
}
}
// printf("%d %d\n",i,f2[i]);
}
int mx=(1<<n1)-1;
for(int i=0;i<(1<<n1);i++)
{
c1[f1[i^mx]][f[i]]++;
}
for(int i=0;i<(1<<n2);i++)
{
c2[f2[i]][i]++;
}
// for(int i=0;i<(1<<n2);i++)
// {
// for(int op=0;op<=1;op++)
// {
// printf("%d %d %d\n",op,i,c1[op][i]);
// }
// }
// printf("-----\n");
// for(int i=0;i<(1<<n2);i++)
// {
// for(int op=0;op<=1;op++)
// {
// printf("%d %d %d\n",op,i,c2[op][i]);
// }
// }
// printf("-----\n");
FWT(c1[0]);
FWT(c2[0]);
FWT(c1[1]);
FWT(c2[1]);
// for(int i=0;i<(1<<n2);i++)
// {
// for(int op=0;op<=1;op++)
// {
// printf("%d %d %d\n",op,i,c1[op][i]);
// }
// }
// printf("-----\n");
// for(int i=0;i<(1<<n2);i++)
// {
// for(int op=0;op<=1;op++)
// {
// printf("%d %d %d\n",op,i,c2[op][i]);
// }
// }
// printf("-----\n");
for(int i=0;i<(1<<n2);i++)
{
for(int op1=0;op1<=1;op1++)
{
for(int op2=0;op2<=1;op2++)
{
h[op1^op2][i]+=c1[op1][i]*c2[op2][i];
//printf("%d %d %d %d??\n",op1,op2,i,c1[op1][i]*c2[op2][i]);
}
}
}
// for(int i=0;i<(1<<n2);i++)
// {
// for(int op=0;op<=1;op++)
// {
// printf("%d %d %d\n",op,i,h[op][i]);
// }
// }
// printf("-----\n");
IFWT(h[0]);
IFWT(h[1]);
long long Res=0;
for(int i=0;i<(1<<n2);i++)
{
Res+=h[(__builtin_popcount(i))&1][i];
}
printf("%lld\n",Res);
}
ABC273G
简单\(dp\),考虑前\(i\)行剩了\(j\)种\(1\)列
转移有点多
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=5005;
int n;
int R[MAXN];
int C[MAXN];
int dp[MAXN][MAXN];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
int Sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&R[i]);
Sum+=R[i];
}
int Spt=0;
int c1=0;
int c2=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&C[i]);
Spt+=C[i];
if(C[i]==1)
{
c1++;
}
else
{
c2++;
}
}
if(Sum!=Spt)
{
printf("0");
return 0;
}
// cerr<<"fc"<<endl;
dp[0][c1]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
if((Sum-j)&1)
{
continue;
}
if(!dp[i-1][j])
{
continue;
}
int k=(Sum-j)/2;
// printf("%d %d %d %d:::\n",i-1,j,k,dp[i-1][j]);
if(R[i]==0)
{
dp[i][j]=((long long)dp[i][j]+dp[i-1][j])%MOD;
}
else if(R[i]==1)
{
if(j)
{
dp[i][j-1]=((long long)dp[i][j-1]+((long long)dp[i-1][j]*j)%MOD)%MOD;
}
dp[i][j+1]=((long long)dp[i][j+1]+((long long)dp[i-1][j]*k)%MOD)%MOD;
}
else
{
dp[i][j]=((long long)dp[i][j]+((long long)dp[i-1][j]*k)%MOD)%MOD;
dp[i][j]=((long long)dp[i][j]+(((long long)dp[i-1][j]*k*j)%MOD))%MOD;
if(j>=2)
{
dp[i][j-2]=((long long)dp[i][j-2]+(((long long)dp[i-1][j]*(j*(j-1)/2))%MOD))%MOD;
}
if(k>=2)
{
dp[i][j+2]=((long long)dp[i][j+2]+((long long)dp[i-1][j]*(k*(k-1)/2))%MOD)%MOD;
}
}
// printf("%d---\n",dp[2][1]);
}
// for(int j=0;j<=n;j++)
// {
// printf("%d %d %d\n",i,j,dp[i][j]);
// }
Sum-=R[i];
}
printf("%d\n",dp[n][0]);
}
// 10
// 10 75 38
// 6 30 99
// 10 17 51
// 1 76 53
// 6 89 48
// 8 14 84
// 1 14 31
// 10 33 33
// 2 85 38
// 10 72 29
ABC272G
随机化爬
Show Code
#include<bits/stdc++.h>
using namespace std;
int Abs(int x)
{
return x>0?x:-x;
}
mt19937 Niuzi(998244353);
const int MAXN=5005;
int n;
int a[MAXN];
map<int,int>Vis;
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int T=50;
while(T--)
{
int x=Niuzi()%n+1;
int t=50;
while(t--)
{
int y=Niuzi()%n+1;
if(x==y)
{
continue;
}
int d=Abs(a[x]-a[y]);
for(int z=2;z*z<=d;z++)
{
if((d%z==0))
{
if(z>2)
{
while(d%z==0)
{
d/=z;
}
Vis.clear();
int maxi=0;
for(int i=1;i<=n;i++)
{
Vis[(a[i])%z]++;
maxi=max(maxi,Vis[a[i]%z]);
}
if(maxi>(n/2))
{
printf("%d",z);
return 0;
}
}
}
}
if(d>2)
{
int z=d;
Vis.clear();
int maxi=0;
for(int i=1;i<=n;i++)
{
Vis[(a[i])%z]++;
maxi=max(maxi,Vis[a[i]%z]);
}
if(maxi>(n/2))
{
printf("%d",z);
return 0;
}
}
}
}
printf("-1\n");
}
// 10
// 10 75 38
// 6 30 99
// 10 17 51
// 1 76 53
// 6 89 48
// 8 14 84
// 1 14 31
// 10 33 33
// 2 85 38
// 10 72 29
ABC325G
可以去竞选弱智吧吧主了/kk
第一眼的思路竟是把所有可以删完的区间处理出来,然后选出最长的不交区间
结果实际上没必要这样处理,直接\(dp\)答案即可,直接找第一个\(o\)和\(i\)处的\(f\)即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=305;
char s[MAXN];
int K;
int dp[MAXN][MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%s",s+1);
scanf("%d",&K);
int n=strlen(s+1);
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;i++)
{
dp[i][i]=1;
dp[i][i-1]=0;
dp[i+1][i]=0;
}
for(int len=2;len<=n;len++)
{
for(int l=1;l+len-1<=n;l++)
{
int r=l+len-1;
for(int k=l;k<r;k++)
{
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
}
if(s[l]=='o')
{
for(int k=l;k<r;k++)
{
if(dp[l+1][k]==0&&s[k+1]=='f')
{
// printf("%d %d %d???\n",l,r,k);
dp[l][r]=min(dp[l][r],max(dp[k+2][r]-K,0));
}
}
}
}
}
// printf("%d\n",dp[2][5]);
printf("%d\n",dp[1][n]);
}
ABC271G
一眼矩乘
初值付错了调了半天
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
long long n;
int x,y;
char s[31];
int cost[25][25];
struct Martix{
int val[24][24];
void clear()
{
memset(val,0,sizeof(val));
}
void init()
{
clear();
for(int i=0;i<24;i++)
{
val[i][i]=1;
}
}
Martix operator*(const Martix x)const{
Martix Res;
Res.clear();
for(int k=0;k<24;k++)
{
for(int i=0;i<24;i++)
{
for(int j=0;j<24;j++)
{
Res.val[i][j]=((long long)Res.val[i][j]+((long long)val[i][k]*x.val[k][j])%MOD)%MOD;
}
}
}
return Res;
}
}A,B;
Martix Pw(Martix Base,long long b)
{
Martix Res;
Res.init();
while(b)
{
if(b&1)
{
Res=Res*Base;
}
Base=Base*Base;
b>>=1;
}
return Res;
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%lld %d %d",&n,&x,&y);
x=((long long)x*inv(100,MOD))%MOD;
y=((long long)y*inv(100,MOD))%MOD;
scanf("%s",s);
int p=1;
for(int i=0;i<24;i++)
{
if(s[i]=='T')
{
p=((long long)p*(1ll-x+MOD)%MOD)%MOD;
}
else
{
p=((long long)p*(1ll-y+MOD)%MOD)%MOD;
}
}
for(int i=0;i<24;i++)
{
for(int j=0;j<24;j++)
{
int Now=(i+1)%24;
int P=1;
while(Now!=j)
{
if(s[Now]=='T')
{
P=((long long)P*(1ll-x+MOD)%MOD)%MOD;
}
else
{
P=((long long)P*(1ll-y+MOD)%MOD)%MOD;
}
Now++;
Now%=24;
}
int v;
if(s[j]=='T')
{
v=x;
}
else
{
v=y;
}
// printf("%d %d %d %d",i+1,j+1,P,v);
P=((long long)P*v)%MOD;
P=((long long)P*inv((1ll-p+MOD)%MOD,MOD))%MOD;
// printf(" %d\n",P);
cost[i][j]=P;
// printf("%d\n",cost[2][1]);
}
}
A.clear();
for(int i=0;i<24;i++)
{
for(int j=0;j<24;j++)
{
A.val[i][j]=cost[i][j];
// printf("%d ",cost[i][j]);
}
// printf("\n");
}
B.clear();
B.val[0][23]=1;
B=B*Pw(A,n);
int Res=0;
for(int i=0;i<24;i++)
{
if(s[i]=='A')
{
Res=((long long)Res+B.val[0][i])%MOD;
}
}
printf("%d\n",Res);
}
ABC326G
简单最小割
Show Code
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int MAXN=200005;
struct Edge{
int val,to,nxt;
}edge[MAXN];
int head[MAXN];
int cnt_edge=1;
void Add(int u,int v,int val)
{
++cnt_edge;
edge[cnt_edge].nxt=head[u];
edge[cnt_edge].val=val;
edge[cnt_edge].to=v;
head[u]=cnt_edge;
return;
}
void add(int u,int v,int val)
{
Add(u,v,val);
Add(v,u,0);
}
int S,T;
int arc[MAXN];
int dis[MAXN];
int bfs()
{
memset(dis,0x3f,sizeof(dis));
queue<int>q;
dis[S]=0;
q.push(S);
while(q.size())
{
int u=q.front();
arc[u]=head[u];
q.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
int w=edge[i].val;
if(!w)
{
continue;
}
if(dis[v]!=0x3f3f3f3f)
{
continue;
}
dis[v]=dis[u]+1;
q.push(v);
}
}
return dis[T]!=0x3f3f3f3f;
}
int dfs(int x,int Cap)
{
if(x==T)
{
return Cap;
}
if(!Cap)
{
return 0;
}
//cerr<<x<<endl;
int Used=0;
for(int i=arc[x];i;i=edge[i].nxt)
{
arc[x]=i;
int v=edge[i].to;
int w=edge[i].val;
if(!w)
{
continue;
}
if(dis[v]==dis[x]+1)
{
int cap=dfs(v,min(Cap,w));
edge[i].val-=cap;
edge[i^1].val+=cap;
Used+=cap;
Cap-=cap;
if(Cap==0)
{
break;
}
}
}
return Used;
}
int dinic()
{
int Maxflow=0;
while(bfs())
{
int Flow=0;
while((Flow=dfs(S,INF)))
{
//cerr<<"fuc"<<endl;
Maxflow+=Flow;
}
}
return Maxflow;
}
int n,m;
int A[55];
int C[55];
int L[55][55];
signed main()
{
//freopen("date.in","r",stdin);
//freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&C[i]);
}
int Res=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&A[i]);
Res+=A[i];
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&L[i][j]);
}
}
S=0;
for(int i=1;i<=n;i++)
{
add(S,i,INF);
for(int j=1;j<=4;j++)
{
add((j-1)*n+i,j*n+i,(j-1)*C[i]);
}
}
for(int i=1;i<=m;i++)
{
add(S,i+5*n,A[i]);
for(int j=1;j<=n;j++)
{
add(i+5*n,(L[i][j]-1)*n+j,INF);
}
}
T=5*n+m+1;
for(int i=1;i<=n;i++)
{
add(i+4*n,T,4*C[i]);
}
// for(int i=0;i<=T;i++)
// {
// for(int j=head[i];j;j=edge[j].nxt)
// {
// printf("%d %d %d\n",i,edge[j].to,edge[j].val);
// }
// }
printf("%d\n",Res-dinic());
}
ABC271Ex
恶心的分类讨论
Show Code
// LUOGU_RID: 132242047
#include<bits/stdc++.h>
using namespace std;
int Abs(int x)
{
return x>0?x:-x;
}
int T;
int zfx[9]={1,1,0,-1,-1,-1,0,1};////
int zfy[9]={0,1,1,1,0,-1,-1,-1};
int rfx[9];////
int rfy[9];
int x,y;
string s;
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&x,&y);
cin>>s;
if(x==0&&y==0)
{
printf("%d\n",0);
continue;
}
for(int i=0;i<8;i++)
{
rfx[i]=zfx[i];
rfy[i]=zfy[i];
}
if(x<0)
{
for(int i=0;i<8;i++)
{
rfx[i]*=-1;
}
x=-x;
}
if(y<0)
{
for(int i=0;i<8;i++)
{
rfy[i]*=-1;
}
y=-y;
}
bool f1=0,f2=0,f3=0,f4=0;
for(int i=0;i<8;i+=2)
{
if(s[i]=='1')
{
if(rfx[i]==1)
{
f1=1;
}
else if(rfy[i]==1)
{
f2=1;
}
else if(rfx[i]==-1)
{
f3=1;
}
else if(rfy[i]==-1)
{
f4=1;
}
}
}
long long Res=3e9+1;
for(int i=0;i<8;i++)
{
if(s[i]=='1')
{
if((i&1))
{
if(rfx[i]==1&&rfy[i]==1)
{
if(x==y)
{
Res=min(Res,1ll*x);
}
}
}
else
{
if(rfx[i]==1)
{
if(y==0)
{
Res=min(Res,1ll*x);
}
}
else if(rfy[i]==1)
{
if(x==0)
{
Res=min(Res,1ll*y);
}
}
}
}
for(int j=0;j<8;j++)
{
if(i==j)
{
continue;
}
if(rfx[i]==-1&&rfy[i]==-1)
{
continue;
}
if(rfx[j]==-1&&rfy[j]==-1)
{
continue;
}
if(s[i]=='1'&&s[j]=='1')
{
if((i&1)&&(j&1))
{
if((rfx[i]==1&&rfy[i]==1))
{
//printf("fuckfucf???\n");
if(x>=y&&(rfy[j]==-1)&&((x+y)%2==0))
{
Res=min(Res,(long long)x);
}
else if(x>=y&&(rfy[j]==-1))
{
if(f2||f4)
{
Res=min(Res,(long long)x+1);
}
if(f1)
{
Res=min(Res,(long long)x);
}
if(f3)
{
Res=min(Res,(long long)x+2);
}
}
else if(x<=y&&(rfx[j]==-1)&&((x+y)%2==0))
{
Res=min(Res,(long long)y);
}
else if(x<=y&&(rfx[j]==-1))
{
if(f1||f3)
{
Res=min(Res,(long long)y+1);
}
if(f2)
{
Res=min(Res,(long long)y);
}
if(f4)
{
Res=min(Res,(long long)y+2);
}
}
}
if((rfx[j]==1&&rfy[j]==1))
{
swap(i,j);
if(x>=y&&(rfy[j]==-1)&&((x+y)%2==0))
{
Res=min(Res,(long long)x);
}
else if(x>=y&&(rfy[j]==-1))
{
if(f2||f4)
{
Res=min(Res,(long long)x+1);
}
if(f1)
{
Res=min(Res,(long long)x);
}
if(f3)
{
Res=min(Res,(long long)x+2);
}
}
else if(x<=y&&(rfx[j]==-1)&&((x+y)%2==0))
{
Res=min(Res,(long long)y);
}
else if(x<=y&&(rfx[j]==-1))
{
if(f1||f3)
{
Res=min(Res,(long long)y+1);
}
if(f2)
{
Res=min(Res,(long long)y);
}
if(f4)
{
Res=min(Res,(long long)y+2);
}
}
swap(i,j);
}
}
else if((i%2==0)&&(j%2==0))
{
if(rfx[i]==1&&rfy[j]==1)
{
Res=min(Res,(long long)x+y);
}
if(rfy[i]==1&&rfx[j]==1)
{
Res=min(Res,(long long)x+y);
}
}
else if(i&1)
{
if(rfx[i]==-1&&rfy[i]==1)
{
if(rfx[j]==1)
{
Res=min(Res,2ll*y+x);
}
}
if(rfx[i]==1&&rfy[i]==1)
{
if(rfx[j]==1&&(x>=y))
{
Res=min(Res,1ll*x);
}
if(rfy[j]==-1&&(x>=y))
{
Res=min(Res,1ll*x+(x-y));
}
if(rfx[j]==-1&&(x<=y))
{
Res=min(Res,1ll*y+(y-x));
}
if(rfy[j]==1&&(x<=y))
{
Res=min(Res,1ll*y);
}
}
if(rfx[i]==1&&rfy[i]==-1)
{
if(rfy[j]==1)
{
Res=min(Res,2ll*x+y);
}
}
}
else if(j&1)
{
swap(i,j);
if(rfx[i]==-1&&rfy[i]==1)
{
if(rfx[j]==1)
{
Res=min(Res,2ll*y+x);
}
}
if(rfx[i]==1&&rfy[i]==1)
{
if(rfx[j]==1&&(x>=y))
{
Res=min(Res,1ll*x);
}
if(rfy[j]==-1&&(x>=y))
{
Res=min(Res,1ll*x+(x-y));
}
if(rfx[j]==-1&&(x<=y))
{
Res=min(Res,1ll*y+(y-x));
}
if(rfy[j]==1&&(x<=y))
{
Res=min(Res,1ll*y);
}
}
if(rfx[i]==1&&rfy[i]==-1)
{
if(rfy[j]==1)
{
Res=min(Res,2ll*x+y);
}
}
swap(i,j);
}
}
}
}
if(Res==3e9+1)
{
printf("-1\n");
}
else
{
printf("%lld\n",Res);
}
}
}
ABC270G
\(BSGS\)半屉
Show Code
#include<bits/stdc++.h>
using namespace std;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int t;
int P,A,B,S,G;
map<int,int>Vis;
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d %d %d",&P,&A,&B,&S,&G);
if(A==0)
{
if(S==G)
{
printf("0\n");
}
else if(B==G)
{
printf("1\n");
}
else{
printf("-1\n");
}
}
else if(A==1)
{
if(S==G)
{
printf("0\n");
}
else
{
int det=((long long)G-S+P)%P;
det=((long long)det*inv(B,P))%P;
printf("%d\n",det);
}
}
else
{
Vis.clear();
B=((long long)B*inv(A-1,P))%P;
G=((long long)G+B)%P;
S=((long long)S+B)%P;
G=((long long)G*inv(S,P))%P;
//printf("%d %d???\n",A,G);
int Lit=sqrt(P);
int Mul=1;
Vis[1]=0;
for(int i=1;i<=Lit;i++)
{
Mul=((long long)Mul*A)%P;
if(i<Lit)
{
if(Vis.find(Mul)==Vis.end())
{
Vis[Mul]=i;
}
}
}
int Km=Mul;
int Res=0x3f3f3f3f;
Mul=1;
for(int i=0;i<=Lit;i++)
{
int lk=((long long)G*inv(Mul,P))%P;
if(Vis.find(lk)!=Vis.end())
{
Res=min(Res,i*Lit+Vis[lk]);
}
Mul=((long long)Mul*Km)%P;
}
if(Res==0x3f3f3f3f)
{
printf("-1\n");
}
else
{
printf("%d\n",Res);
}
}
}
}
ABC269G
背包种类数只有\(\sqrt m\)个
原因是考虑\(\sum|A_i-B_i|\le m\),这是经典结构
然后就单调队列多重背包,负的和正的分开算即可
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+5;
int n;
int M;
int A[MAXN];
int B[MAXN];
map<int,int>D;
int dp[MAXN*2];
int dq[MAXN];
int tmp[MAXN*2];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&M);
int Suma=0;
for(int i=1;i<=n;i++)
{
scanf("%d %d",&A[i],&B[i]);
D[B[i]-A[i]]++;
Suma+=A[i];
}
vector<pair<int,int> >V;
for(auto it=D.begin();it!=D.end();it++)
{
V.push_back((*it));
//printf("%d %d???\n",(*it).first,(*it).second);
}
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
int Key=0;
sort(V.begin(),V.end());
for(int i=0;i<V.size();i++)
{
int Lit=V[i].second;
int c=V[i].first;
for(int j=0;j<=2*M;j++)
{
tmp[j]=dp[j];
}
if(c<0)
{
c=-c;
for(int j=0;j<c;j++)
{
int head=1;
int tail=0;
dq[++tail]=0;
for(int k=1;j+k*c<=M;k++)
{
while(head<=tail&&k-dq[head]>Lit)
{
head++;
}
dp[j+k*c]=min(dp[j+k*c],tmp[j+dq[head]*c]+(k-(dq[head])));
while(head<=tail&&tmp[j+k*c]-k<=tmp[j+dq[tail]*c]-dq[tail])
{
tail--;
}
dq[++tail]=k;
}
}
//printf("%d %d::\n",c,dp[2]);
}
else if(c>0)
{
Key=i;
break;
}
}
memset(tmp,0x3f,sizeof(tmp));
for(int i=0;i<=M;i++)
{
tmp[M-i]=dp[i];
//printf("%d %d:\n",i,dp[i]);
}
for(int i=0;i<=2*M;i++)
{
dp[i]=tmp[i];
// printf("%d %d:\n",i,dp[i]);
}
for(int i=Key;i<V.size();i++)
{
int Lit=V[i].second;
int c=V[i].first;
for(int j=0;j<=2*M;j++)
{
tmp[j]=dp[j];
}
for(int j=0;j<c;j++)
{
int head=1;
int tail=0;
dq[++tail]=0;
for(int k=1;j+k*c<=2*M;k++)
{
while(head<=tail&&k-dq[head]>Lit)
{
head++;
}
dp[j+k*c]=min(dp[j+k*c],tmp[j+dq[head]*c]+(k-(dq[head])));
while(head<=tail&&tmp[j+k*c]-k<=tmp[j+dq[tail]*c]-dq[tail])
{
tail--;
}
dq[++tail]=k;
}
}
}
// printf("------\n");
// for(int i=0;i<=2*M;i++)
// {
// printf("%d %d:\n",i,dp[i]);
// }
for(int i=0;i<=M;i++)
{
int Rg=dp[i-Suma+M];
if(Rg==0x3f3f3f3f)
{
printf("-1\n");
}
else
{
printf("%d\n",Rg);
}
}
}
ABC217Ex
\(dp_i=\frac{\sum\limits_{i=1}^ndp_{\max i-1,A_i}}{n}+1\)
设\(c_i\)为\(\sum\limits_{j=1}^n[A_j< i]\)的数量
即\(dp_i=\frac{dp_{i-1}c_i}{n}+\frac{\sum\limits_{j=c_i+1}^ndp_j}{n}+1\)
\(dp_{i-1}=\frac{n}{c_i}dp_i-\frac{n}{c_i}1-\frac{\sum\limits_{j=c_i+1}^ndp_j}{c_i}\)
然后主元\(+\)矩阵
Show Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=998244353;
const int MAXN=2e5+5;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int n;
long long a[MAXN];
long long b[MAXN];
pair<int,int>dp[MAXN];
pair<int,int>operator+(const pair<int,int>x,const pair<int,int>y)
{
return make_pair(((long long)x.first+y.first)%MOD,((long long)x.second+y.second)%MOD);
}
pair<int,int>operator*(const pair<int,int>x,const pair<int,int> y)
{
return make_pair((((long long)x.first*y.second)%MOD+((long long)y.first*x.second)%MOD)%MOD,((long long)x.second*y.second)%MOD);
}
struct Martix{
pair<int,int>val[2][2];
void clear()
{
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
val[i][j]=make_pair(0,0);
}
}
}
void init()
{
clear();
for(int i=0;i<2;i++)
{
val[i][i]=make_pair(0,1);
}
}
void print()
{
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
printf("(%lld,%lld) ",val[i][j].first,val[i][j].second);
}
printf("\n");
}
}
Martix operator*(const Martix x)const{
Martix Res;
Res.clear();
for(int k=0;k<2;k++)
{
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
Res.val[i][j]=Res.val[i][j]+val[i][k]*x.val[k][j];
}
}
}
return Res;
}
};
Martix Pw(Martix Base,long long b)
{
Martix res;
res.init();
while(b)
{
if(b&1)
{
res=res*Base;
}
Base=Base*Base;
b>>=1;
}
return res;
}
map<long long,int>V;
signed main()
{
freopen("date.in","r",stdin);
freopen("date.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
b[i]=a[i];
V[a[i]]++;
}
int Cnt=unique(b+1,b+1+n)-b-1;
dp[Cnt]=make_pair(1,0);
pair<int,int>Pre=dp[Cnt]*make_pair(0,V[b[Cnt]]);
for(int i=Cnt-1;i>=1;i--)
{
long long Times=(b[i+1]-b[i]);
int c=lower_bound(a+1,a+1+n,b[i+1])-a-1;
// printf("%lld %lld %lld %lld??\n",Pre.first,Pre.second,c,Times);
Martix A,B;
A.clear();
A.val[0][0]=dp[i+1];
A.val[0][1]=make_pair(0,1);
B.val[0][0]=make_pair(0,((long long)n*inv(c,MOD))%MOD);
B.val[1][1]=make_pair(0,1);
B.val[1][0]=make_pair(0,((long long)n*inv(c,MOD))%MOD)+make_pair(0,inv(c,MOD))*Pre;
B.val[1][0].first=(MOD-B.val[1][0].first)%MOD;
B.val[1][0].second=(MOD-B.val[1][0].second)%MOD;
B=Pw(B,Times);
A=A*B;
dp[i]=A.val[0][0];
Pre=Pre+dp[i]*make_pair(0,V[b[i]]);
}
int Res=(((long long)MOD-dp[1].second)*inv(dp[1].first,MOD))%MOD;
printf("%lld\n",Res);
}
ABC268G
被诈骗了/kk
最开始没看出来,实际上两个串如果不是前后缀关系,则对于它们的先后关系是随机的,即\(j\)对\(i\)的贡献为\(\dfrac{1}{2}\)
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=5e5+5;
int n,m;
string S[MAXN];
int Tree[MAXN][27];
int cnt_node;
int Num1[MAXN];
int Num2[MAXN];
void Insert(string s)
{
int p=0;
for(int i=0;i<s.size();i++)
{
if(!Tree[p][s[i]-'a'])
{
Tree[p][s[i]-'a']=++cnt_node;
}
p=Tree[p][s[i]-'a'];
}
Num1[p]++;
Num2[p]++;
}
void dfs(int p)
{
for(int i=0;i<26;i++)
{
if(Tree[p][i])
{
dfs(Tree[p][i]);
Num2[p]+=Num2[Tree[p][i]];
}
}
}
int inv2=MOD-MOD/2;
int Query(string x)
{
int p=0;
int a=0;
for(int i=0;i<x.size();i++)
{
p=Tree[p][x[i]-'a'];
a+=Num1[p];
}
int b=Num2[p];
//printf("%d %d\n",a,b);
return (((long long)n-a-b+1)*inv2+a)%MOD;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>S[i];
Insert(S[i]);
}
dfs(0);
for(int i=1;i<=n;i++)
{
printf("%d\n",Query(S[i]));
}
}
ABC268Ex
AC自动机板子
Show Code
// LUOGU_RID: 132443105
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+5;
int n,m;
int Tree[MAXN][27];////
int Num[MAXN];
int cnt_node;////
void Insert(string x)
{
int p=0;
for(int i=0;i<x.size();i++)
{
if(!Tree[p][x[i]-'a'+1])
{
Tree[p][x[i]-'a'+1]=++cnt_node;
}
p=Tree[p][x[i]-'a'+1];
}
Num[p]++;
}
void ACAM()
{
queue<int>q;
for(int i=1;i<=26;i++)
{
if(Tree[0][i])
{
q.push(Tree[0][i]);
}
}
while(q.size())
{
int temp=q.front();
//cerr<<temp<<endl;
q.pop();
for(int i=1;i<=26;i++)
{
if(Tree[temp][i])
{
q.push(Tree[temp][i]);
Tree[Tree[temp][i]][0]=Tree[Tree[temp][0]][i];
}
else
{
Tree[temp][i]=Tree[Tree[temp][0]][i];
}
}
}
}
vector<int>g[MAXN];
string S,T;
void dfs(int x)
{
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
Num[v]+=Num[x];
dfs(v);
}
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
cin>>S;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>T;
Insert(T);
}
//cerr<<"fuck"<<endl;
ACAM();
for(int i=1;i<=cnt_node;i++)
{
g[Tree[i][0]].push_back(i);
}
dfs(0);
int p=0;
int Res=0;
for(int i=0;i<S.size();i++)
{
p=Tree[p][S[i]-'a'+1];
if(Num[p])
{
p=0;
++Res;
}
}
printf("%d\n",Res);
}
ABC267G
简单\(dp\),最开始把值相同的合并成一段,结果搞出来个\(n^3\)
其实直接算就行了
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=5005;
int n,k;
int a[MAXN];
int Same[MAXN];
int dp[MAXN][MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=i;j++)
{
if(dp[i-1][j])
{
dp[i][j]=((long long)dp[i][j]+((long long)dp[i-1][j]*(Same[a[i]]+j+1))%MOD)%MOD;
dp[i][j+1]=((long long)dp[i][j+1]+((long long)dp[i-1][j]*(i-Same[a[i]]-j-1))%MOD)%MOD;
}
}
Same[a[i]]++;
}
printf("%d\n",dp[n][k]);
}
ABC267Ex
NTT板子
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int g=3;
const int MAXN=1e6+5;///
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{///
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int rev[MAXN*2];
struct Poly{
vector<int>V;
void NTT(int Lit,int op)
{
while(V.size()<(1<<Lit))
{//
V.push_back(0);
}
for(int i=0;i<(1<<Lit);i++)
{
rev[i]=(rev[i>>1]>>1)|(i&1)<<(Lit-1);
}
for(int i=0;i<(1<<Lit);i++)
{
if(i<rev[i])
{
swap(V[i],V[rev[i]]);
}
}
for(int len=1;len<(1<<Lit);len<<=1)
{
int w=Pow(g,(MOD-1)/(len<<1),MOD);
if(op==-1)
{
w=inv(w,MOD);
}
for(int i=0;i<(1<<Lit);i+=(len<<1))
{
for(int j=i,wn=1;j<(i+len);j++,wn=((long long)wn*w)%MOD)
{
int x=V[j];
int y=V[j+len];
V[j]=((long long)x+((long long)y*wn)%MOD)%MOD;
V[j+len]=((long long)x-((long long)y*wn)%MOD+MOD)%MOD;
}
}
}
if(op==-1)
{
int mkx=inv((1<<Lit),MOD);
for(int i=0;i<(1<<Lit);i++)
{
V[i]=((long long)V[i]*mkx)%MOD;
}
}
}
};
Poly Mul(Poly x,Poly y)
{
int N=x.V.size();
int M=y.V.size();
int C=N+M-1;
while(x.V.size()<C)
{
x.V.push_back(0);
}
while(y.V.size()<C)
{
y.V.push_back(0);
}
int nx=1;
int nox=0;
while(nx<C)
{
nx<<=1;
nox++;
}
x.NTT(nox,1);
y.NTT(nox,1);
for(int i=0;i<(1<<nox);i++)
{
x.V[i]=((long long)x.V[i]*y.V[i])%MOD;
}
x.NTT(nox,-1);
while(x.V.size()>C)
{
x.V.pop_back();
}
return x;
}
int n;
int A[MAXN];
int Ct[15];
int fac[MAXN];
int inv_fac[MAXN];
int C(int n,int m)
{
if(n<m||m<0)
{
return 0;
}
if((n==m)||(m==0))
{
return 1;
}
return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}
int m;
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
fac[0]=1;
for(int i=1;i<=MAXN-5;i++)
{
fac[i]=((long long)fac[i-1]*i)%MOD;
}
inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
for(int i=MAXN-5-1;i>=1;i--)
{
inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
}
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&A[i]);
Ct[A[i]]++;
}
Poly F,G;
F.V.resize(1,1);
G.V.resize(1,1);
for(int i=1;i<=10;i++)
{
Poly A,B;
A.V.resize((Ct[i]+1)*i,0);
B.V.resize((Ct[i]+1)*i,0);
for(int j=0;j<=Ct[i];j++)
{
A.V[j*i]=C(Ct[i],j);
B.V[j*i]=C(Ct[i],j);
if(j&1)
{
B.V[j*i]=(MOD-B.V[j*i]);
}
}
F=Mul(F,A);
G=Mul(G,B);
}
int inv2=(MOD-MOD/2);
if(F.V.size()<=m)
{
printf("0\n");
}
else
{
int zhmnb=(F.V[m]-G.V[m]+MOD)%MOD;
zhmnb=((long long)zhmnb*inv2)%MOD;
printf("%d\n",zhmnb);
}
}
ABC266Ex
CDQ板子
Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=1e5+5;
int n;
struct node{
int t,x,y,v;
int ind;
}a[MAXN],tmp[MAXN];
bool cmp(node x,node y)
{
if(x.y==y.y)
{
return x.t<y.t;
}
return x.y<y.y;
}
bool kmp(node x,node y)
{
return x.t-x.y-x.x<y.t-y.y-y.x;
}
long long dp[MAXN];
struct Seg{
long long date;
int lc,rc;
}Tree[MAXN*10];
int cnt_node;
int rt;
int New()
{
++cnt_node;
Tree[cnt_node].lc=Tree[cnt_node].rc=0;
Tree[cnt_node].date=0;
return cnt_node;
}
void Insert(int &p,int l,int r,int k,long long x)
{
if(!p)
{
p=New();
}
Tree[p].date=max(Tree[p].date,x);
if(l==r)
{
return;
}
int mid=((long long)l+r)>>1;
if(k<=mid)
{
Insert(ls,l,mid,k,x);
}
else
{
Insert(rs,mid+1,r,k,x);
}
}
long long Query(int p,int l,int r,int ql,int qr)
{
if(!p)
{
return 0;
}
if(l>=ql&&r<=qr)
{
return Tree[p].date;
}
int mid=((long long)l+r)>>1;
long long Res=0;
if(ql<=mid)
{
Res=max(Res,Query(ls,l,mid,ql,qr));
}
if(qr>mid)
{
Res=max(Res,Query(rs,mid+1,r,ql,qr));
}
return Res;
}
void solve(int l,int r)
{
if(l==r)
{
return;
}
int mid=(l+r)>>1;
solve(l,mid);
int pl=l,pr=mid+1;
cnt_node=0;
rt=0;
for(int i=l;i<=r;i++)
{
tmp[i]=a[i];
}
sort(a+l,a+mid+1,kmp);
sort(a+mid+1,a+r+1,kmp);
//printf("%d %d----\n",l,r);
while(pl<=mid&&pr<=r)
{
if(a[pl].t-a[pl].y-a[pl].x<=a[pr].t-a[pr].y-a[pr].x)
{
Insert(rt,-2e9,2e9,a[pl].t-a[pl].y+a[pl].x,dp[a[pl].ind]);
// printf("%d %d:::\n",a[pl].ind,a[pl].t-a[pl].y+a[pl].x);
pl++;
}
else
{
dp[a[pr].ind]=max(dp[a[pr].ind],Query(rt,-2e9,2e9,-2e9,a[pr].t-a[pr].y+a[pr].x)+a[pr].v);
// printf("%d %d:::\n",a[pr].ind,a[pr].t-a[pr].y+a[pr].x);
pr++;
}
}
while(pl<=mid)
{
Insert(rt,-2e9,2e9,a[pl].t-a[pl].y+a[pl].x,dp[a[pl].ind]);
//printf("%d %d:::\n",a[pl].ind,a[pl].t-a[pl].y+a[pl].x);
pl++;
}
while(pr<=r)
{
dp[a[pr].ind]=max(dp[a[pr].ind],Query(rt,-2e9,2e9,-2e9,a[pr].t-a[pr].y+a[pr].x)+a[pr].v);
//printf("%d %d:::\n",a[pr].ind,a[pr].t-a[pr].y+a[pr].x);
pr++;
}
for(int i=l;i<=r;i++)
{
a[i]=tmp[i];
}
solve(mid+1,r);
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
if(n==1||n==0)
{
printf("0\n");
return 0;
}
bool f=1;
for(int i=1;i<=n;i++)
{
scanf("%d %d %d %d",&a[i].t,&a[i].x,&a[i].y,&a[i].v);
a[i].ind=i;
dp[i]=-1e18;
if(a[i].t==0&&a[i].x==0&&a[i].y==0)
{
f=0;
dp[i]=a[i].v;
}
}
if(f)
{
a[++n]=(node){0,0,0,0,0};
dp[0]=0;
}
sort(a+1,a+1+n,cmp);
solve(1,n);
long long Res=0;
for(int i=0;i<=n;i++)
{
Res=max(Res,dp[i]);
}
printf("%lld\n",Res);
// for(int i=0;i<n;i++)
// {
// printf("%d\n",dp[i]);
// }
}
ABC265G
线段树半屉
Show Code
#include<bits/stdc++.h>
#define ls p<<1
#define rs (p<<1)|1
using namespace std;
const int MAXN=1e5+5;
struct Date{
int date[3];
long long res[3][3];
};
struct Seg{
Date d;
int lazy[3];
int l,r;
}Tree[MAXN*4];
int tmpr[3][3];
int tmpd[3];
Date Merge(Date x,Date y)
{
Date res;
for(int i=0;i<=2;i++)
{
res.date[i]=x.date[i]+y.date[i];
}
for(int i=0;i<=2;i++)
{
for(int j=0;j<=2;j++)
{
res.res[i][j]=x.res[i][j]+y.res[i][j];
}
}
for(int i=0;i<=2;i++)
{
for(int j=0;j<=2;j++)
{
res.res[i][j]+=((long long)x.date[i]*y.date[j]);
}
}
return res;
}
void push_up(int p)
{
Tree[p].d=Merge(Tree[ls].d,Tree[rs].d);
}
void push_down(int p)
{
if(Tree[p].lazy[0]!=-1)
{
for(int i=0;i<=2;i++)
{
tmpd[i]=Tree[ls].d.date[i];
Tree[ls].d.date[i]=0;
for(int j=0;j<=2;j++)
{
tmpr[i][j]=Tree[ls].d.res[i][j];
Tree[ls].d.res[i][j]=0;
}
}
for(int i=0;i<=2;i++)
{
Tree[ls].d.date[Tree[p].lazy[i]]+=tmpd[i];
for(int j=0;j<=2;j++)
{
Tree[ls].d.res[Tree[p].lazy[i]][Tree[p].lazy[j]]+=tmpr[i][j];
}
}
if(Tree[ls].lazy[0]==-1)
{
for(int i=0;i<=2;i++)
{
Tree[ls].lazy[i]=Tree[p].lazy[i];
}
}
else
{
for(int i=0;i<=2;i++)
{
Tree[ls].lazy[i]=Tree[p].lazy[Tree[ls].lazy[i]];
}
}
for(int i=0;i<=2;i++)
{
tmpd[i]=Tree[rs].d.date[i];
Tree[rs].d.date[i]=0;
for(int j=0;j<=2;j++)
{
tmpr[i][j]=Tree[rs].d.res[i][j];
Tree[rs].d.res[i][j]=0;
}
}
for(int i=0;i<=2;i++)
{
Tree[rs].d.date[Tree[p].lazy[i]]+=tmpd[i];
for(int j=0;j<=2;j++)
{
Tree[rs].d.res[Tree[p].lazy[i]][Tree[p].lazy[j]]+=tmpr[i][j];
}
}
if(Tree[rs].lazy[0]==-1)
{
for(int i=0;i<=2;i++)
{
Tree[rs].lazy[i]=Tree[p].lazy[i];
}
}
else
{
for(int i=0;i<=2;i++)
{
Tree[rs].lazy[i]=Tree[p].lazy[Tree[rs].lazy[i]];
}
}
Tree[p].lazy[0]=-1;
}
}
int n;
int a[MAXN];
void Build(int p,int l,int r)
{
Tree[p].l=l;
Tree[p].r=r;
Tree[p].lazy[0]=-1;
if(l==r)
{
Tree[p].d.date[a[l]]=1;
return;
}
int mid=(l+r)>>1;
Build(ls,l,mid);
Build(rs,mid+1,r);
push_up(p);
}
void Update(int p,int l,int r,vector<int>Lazy)
{
if(Tree[p].l>=l&&Tree[p].r<=r)
{
for(int i=0;i<=2;i++)
{
tmpd[i]=Tree[p].d.date[i];
Tree[p].d.date[i]=0;
for(int j=0;j<=2;j++)
{
tmpr[i][j]=Tree[p].d.res[i][j];
Tree[p].d.res[i][j]=0;
}
}
for(int i=0;i<=2;i++)
{
Tree[p].d.date[Lazy[i]]+=tmpd[i];
for(int j=0;j<=2;j++)
{
Tree[p].d.res[Lazy[i]][Lazy[j]]+=tmpr[i][j];
}
}
if(Tree[p].lazy[0]==-1)
{
for(int i=0;i<=2;i++)
{
Tree[p].lazy[i]=Lazy[i];
}
}
else
{
for(int i=0;i<=2;i++)
{
Tree[p].lazy[i]=Lazy[Tree[p].lazy[i]];
}
}
return;
}
int mid=(Tree[p].l+Tree[p].r)>>1;
push_down(p);
if(l<=mid)
{
Update(ls,l,r,Lazy);
}
if(r>mid)
{
Update(rs,l,r,Lazy);
}
push_up(p);
}
Date Query(int p,int l,int r)
{
if(Tree[p].l>=l&&Tree[p].r<=r)
{
return Tree[p].d;
}
push_down(p);
int mid=(Tree[p].l+Tree[p].r)>>1;
if(l<=mid&&r>mid)
{
return Merge(Query(ls,l,r),Query(rs,l,r));
}
else if(l<=mid)
{
return Query(ls,l,r);
}
else
{
return Query(rs,l,r);
}
}
int q,op,l,r,x,y,z;
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
Build(1,1,n);
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d %d",&l,&r);
Date Rk=Query(1,l,r);
long long Res=0;
for(int i=0;i<=2;i++)
{
for(int j=0;j<i;j++)
{
Res+=Rk.res[i][j];
}
}
printf("%lld\n",Res);
}
else
{
scanf("%d %d %d %d %d",&l,&r,&x,&y,&z);
vector<int>Krp;
Krp.clear();
Krp.push_back(x);
Krp.push_back(y);
Krp.push_back(z);
Update(1,l,r,Krp);
}
}
}
ABC264G
Spfa半屉
Show Code
#include<bits/stdc++.h>
using namespace std;
int n;
string a,b;
int P[200005];
int Hash(string s)
{
int H=0;
for(int i=0;i<s.size();i++)
{
H=H*27+(s[i]-'a'+1);
}
return H;
}
vector<pair<int,long long> >g[200005];
long long dp[200005];
int rd[200005];
int vis[200005];
int tot[200005];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
while(n--)
{
cin>>a;
scanf("%d",&P[Hash(a)]);
}
for(int i=0;i<=26;i++)
{
for(int j=0;j<=26;j++)
{
a.clear();
if(i)
{
a+=i-1+'a';
}
if(j)
{
a+=j-1+'a';
}
if(a.size())
{
for(int k=1;k<=26;k++)
{
string b=a+(char)(k+'a'-1);
long long Tmp=0;
for(int l=0;l<b.size();l++)
{
int H=0;
for(int r=l;r<b.size();r++)
{
H=H*27+(b[r]-'a'+1);
if(r==b.size()-1)
{
Tmp+=P[H];
}
}
}
// cout<<a<<" "<<b<<" "<<Tmp<<endl;
if(b.size()>=3)
{
b.erase(b.begin(),b.begin()+1);
}
g[Hash(a)].push_back(make_pair(Hash(b),Tmp));
// cout<<a<<" "<<b<<" "<<Tmp<<" "<<endl;
// if(Hash(b)==82)
// {
// cout<<b<<" "<<"djiijsfssfjkskfjksfkjsk"<<endl;
// }
// if(Hash(a)==82)
// {
// cout<<a<<" "<<"djiijsfssfjkskfjksfkjsk"<<endl;
// }
}
}
}
}
string NYH="z";
NYH+='z';
NYH+='z';
int Cnt=Hash(NYH);
memset(dp,-0x3f,sizeof(dp));
for(int i=1;i<=26;i++)
{
g[0].push_back(make_pair(i,P[i]));
}
dp[0]=0;
queue<int>q;
q.push(0);
while(q.size())
{
int temp=q.front();
q.pop();
vis[temp]=0;
// printf("%d %lld??\n",temp,dp[temp]);
if(tot[temp]>Cnt)
{
printf("Infinity\n");
return 0;
}
tot[temp]++;
for(int i=0;i<g[temp].size();i++)
{
int v=g[temp][i].first;
int w=g[temp][i].second;
if(dp[v]<dp[temp]+w)
{
dp[v]=dp[temp]+w;
// if(v==29)
// {
// printf("%d %d %d----\n",v,dp[v],temp);
// }
if(vis[v])
{
continue;
}
vis[v]=1;
q.push(v);
}
}
}
long long Res=-0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=Cnt;i++)
{
Res=max(Res,dp[i]);
// if(dp[i]==10)
// {
// printf("jdkf%d\n",i);
// }
}
printf("%lld\n",Res);
}
ABC264Ex
简单Dp
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
const int MOD=998244353;
int n;
int P[MAXN];
int dep[MAXN];
int dp[MAXN][21][2];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
scanf("%d",&P[i]);
}
dep[1]=1;
printf("%d\n",1);
dp[1][1][2]=1;
for(int i=2;i<=n;i++)
{
dep[i]=dep[P[i]]+1;
if(dep[i]<=20)
{
dp[i][1][2]=1;
int d=2;
int Now=P[i];
int Pre=i;
int Pv=0;
while(Now)
{
int Nv=dp[Now][d][2];
dp[Now][d][1]=((long long)dp[Now][d][1]-Pv+MOD)%MOD;
dp[Now][d][2]=((long long)dp[Now][d][2]-((long long)Pv*dp[Now][d][1])%MOD+MOD)%MOD;
dp[Now][d][2]=((long long)dp[Now][d][2]+((long long)dp[Pre][d-1][2]*dp[Now][d][1])%MOD)%MOD;
dp[Now][d][1]=((long long)dp[Now][d][1]+dp[Pre][d-1][2])%MOD;
Pre=Now;
Pv=Nv;
Now=P[Now];
d++;
}
}
int Res=0;
for(int j=1;j<=20;j++)
{
Res=((long long)Res+dp[1][j][2])%MOD;
}
printf("%d\n",Res);
}
}
ABC263G
小丑<——
奇偶分类就是网络流,不过要特殊处理\(1\)
贪心得想就是先匹配不是\(1\)得再调整
这里直接在残余网络上跑即可
Show Code
#include<bits/stdc++.h>
#define INF 1e9
#define int long long
using namespace std;
const int MAXN=200005;
struct Edge{
int val,to,nxt;
}edge[MAXN];
int head[MAXN];
int cnt_edge=1;
void Add(int u,int v,int val)
{
++cnt_edge;
edge[cnt_edge].nxt=head[u];
edge[cnt_edge].val=val;
edge[cnt_edge].to=v;
head[u]=cnt_edge;
return;
}
void add(int u,int v,int val)
{
Add(u,v,val);
Add(v,u,0);
}
int S,T;
int arc[MAXN];
int dis[MAXN];
int bfs()
{
memset(dis,0x3f,sizeof(dis));
queue<int>q;
dis[S]=0;
q.push(S);
while(q.size())
{
int u=q.front();
arc[u]=head[u];
q.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
int w=edge[i].val;
if(!w)
{
continue;
}
if(dis[v]!=0x3f3f3f3f3f3f3f3f)
{
continue;
}
dis[v]=dis[u]+1;
q.push(v);
}
}
return dis[T]!=0x3f3f3f3f3f3f3f3f;
}
int dfs(int x,int Cap)
{
if(x==T)
{
return Cap;
}
if(!Cap)
{
return 0;
}
//cerr<<x<<endl;
int Used=0;
for(int i=arc[x];i;i=edge[i].nxt)
{
arc[x]=i;
int v=edge[i].to;
int w=edge[i].val;
if(!w)
{
continue;
}
if(dis[v]==dis[x]+1)
{
int cap=dfs(v,min(Cap,w));
edge[i].val-=cap;
edge[i^1].val+=cap;
Used+=cap;
Cap-=cap;
if(Cap==0)
{
break;
}
}
}
return Used;
}
int dinic()
{
int Maxflow=0;
while(bfs())
{
int Flow=0;
while((Flow=dfs(S,INF)))
{
//cerr<<"fuc"<<endl;
Maxflow+=Flow;
}
}
return Maxflow;
}
int n;
int a[105];
int b[105];
bool ck(int x)
{
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
return 0;
}
}
return 1;
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%lld",&n);
vector<pair<int,int> >Odd,Even;
T=n+1;
S=0;
for(int i=1;i<=n;i++)
{
scanf("%lld %lld",&a[i],&b[i]);
if(a[i]&1)
{
Odd.push_back(make_pair(a[i],b[i]));
}
else
{
Even.push_back(make_pair(a[i],b[i]));
}
}
int Ke=-1;
for(int i=0;i<Odd.size();i++)
{
int v=Odd[i].first;
if(v==1)
{
Ke=i;
}
else
{
add(S,i+1,Odd[i].second);
}
}
for(int i=0;i<Even.size();i++)
{
add(i+1+Odd.size(),T,Even[i].second);
}
for(int i=0;i<Odd.size();i++)
{
for(int j=0;j<Even.size();j++)
{
if(ck(Odd[i].first+Even[j].first))
{
add(i+1,j+1+Odd.size(),INF);
}
}
}
int kx=dinic();
if(Ke!=-1)
{
add(S,Ke+1,Odd[Ke].second);
int Nx=dinic();
kx+=(edge[cnt_edge-1].val/2)+Nx;
}
printf("%lld\n",kx);
}
ABC263Ex
二分明显
对于每条与直线相交得圆,我们处理出该直线的覆盖的角度
可以发现有交即角度区间相交且不包含
这里虽然是环状的,不过我们可以取补集让它不会越过\(0\)
Show Code
#include<bits/stdc++.h>
#define x1 Fgfpf
#define y1 djfngg
#define x2 igdo
#define y2 jdfgdjggg
#define eps 1e-4
using namespace std;
const int MAXN=5e4+5;
const double phi=acos(-1);
int n,k;
struct Slope{
double A,B,C;
}a[MAXN];
bool G(double a,double b,double c)
{
return b*b>=4*a*c;
}
pair<double,double>F(double a,double b,double c)
{
return make_pair((-b+sqrt(b*b-4*a*c))/(2.0*a),(-b-sqrt(b*b-4*a*c))/(2.0*a));
}
double lsh[MAXN*2];
int Bit[MAXN*2];
int lowbit(int x)
{
return x&(-x);
}
int Cnt=0;
void update(int k,int x)
{
for(int i=k;i<=Cnt;i+=lowbit(i))
{
Bit[i]+=x;
}
}
int Sum(int k)
{
int Res=0;
for(int i=k;i>=1;i-=lowbit(i))
{
Res+=Bit[i];
}
return Res;
}
vector<int>Rec[MAXN*2];
bool check(double r)
{
vector<pair<double,double> >V;
vector<pair<int,int> >U;
for(int i=1;i<=n;i++)
{
if(a[i].B)
{
if(G((a[i].A*a[i].A)*1.0/(a[i].B*a[i].B)+1,2.0*a[i].A*a[i].C/(a[i].B*a[i].B),(a[i].C*a[i].C)*1.0/(a[i].B*a[i].B)-r*r))
{
auto fkg=F((a[i].A*a[i].A)*1.0/(a[i].B*a[i].B)+1,2.0*a[i].A*a[i].C/(a[i].B*a[i].B),(a[i].C*a[i].C)*1.0/(a[i].B*a[i].B)-r*r);
double x1=fkg.first;
double x2=fkg.second;
double y1,y2;
if(a[i].B==0)
{
y1=sqrt(r*r-x1*x1);
y2=-sqrt(r*r-x1*x1);
}
else
{
y1=-(a[i].A*x1/a[i].B+a[i].C/a[i].B);
y2=-(a[i].A*x2/a[i].B+a[i].C/a[i].B);
}
double L=atan2(x1,y1);
double R=atan2(x2,y2);
if(L<0)
{
L+=2*phi;
}
if(R<0)
{
R+=2*phi;
}
if(L>R)
{
swap(L,R);
}
//printf("%lf %lf %lf %lf %lf %lf %d\n",x1,y1,x2,y2,L,R,i);
V.push_back(make_pair(L,R));
}
}
else
{
double x1=-a[i].C*1.0/a[i].A;
double x2=-a[i].C*1.0/a[i].A;;
if(x1>=-r&&x1<=r)
{
double y1,y2;
if(a[i].B==0)
{
y1=sqrt(r*r-x1*x1);
y2=-sqrt(r*r-x1*x1);
}
else
{
y1=-(a[i].A*x1/a[i].B+a[i].C/a[i].B);
y2=-(a[i].A*x2/a[i].B+a[i].C/a[i].B);
}
double L=atan2(x1,y1);
double R=atan2(x2,y2);
if(L<0)
{
L+=2*phi;
}
if(R<0)
{
R+=2*phi;
}
if(L>R)
{
swap(L,R);
}
//printf("%lf %lf %lf %lf %lf %lf %d\n",x1,y1,x2,y2,L,R,i);
V.push_back(make_pair(L,R));
}
}
}
Cnt=0;
for(int i=0;i<V.size();i++)
{
lsh[++Cnt]=V[i].first;
lsh[++Cnt]=V[i].second;
}
sort(lsh+1,lsh+1+Cnt);
Cnt=unique(lsh+1,lsh+1+Cnt)-lsh-1;
for(int i=1;i<=Cnt;i++)
{
Bit[i]=0;
Rec[i].clear();
}
for(int i=0;i<V.size();i++)
{
U.push_back(make_pair(0,0));
U[i].first=lower_bound(lsh+1,lsh+1+Cnt,V[i].first)-lsh;
U[i].second=lower_bound(lsh+1,lsh+1+Cnt,V[i].second)-lsh;
Rec[U[i].second].push_back(U[i].first);
//printf("%d %d\n",U[i].first,U[i].second);
}
int Tot=0;
for(int i=1;i<=Cnt;i++)
{
for(int j=0;j<Rec[i].size();j++)
{
int v=Rec[i][j];
Tot+=Sum(v);
}
for(int j=0;j<Rec[i].size();j++)
{
int v=Rec[i][j];
update(v+1,1);
update(i+1,-1);
}
}
return Tot>=k;
}
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lf %lf %lf",&a[i].A,&a[i].B,&a[i].C);
}
//printf("%d\n",check(5));
//printf("%d?\n",check(2));
double l=0;
double r=1e9;
while(r-l>eps)
{
double mid=(l+r)*1.0/2;
if(check(mid))
{
r=mid;
}
else
{
l=mid;
}
}
printf("%lf\n",l);
}
ABC262G
zz区间\(dp\)
最开始想偏了,搞出来个\(n^3\)的类似物,结果处理不了值相同的
实际上直接记录\(dp_{l,r,lv,rv}\)表示\([l,r]\)值在\([lv,rv]\)的答案即可
转移直接枚举和\(l\)一起填的数即可
Show Code
#include<bits/stdc++.h>
using namespace std;
int n;
int a[55];
int dp[55][55][55][55];
int dfs(int l,int r,int lv,int rv)
{
if(dp[l][r][lv][rv]!=-1)
{
return dp[l][r][lv][rv];
}
if(l>r)
{
return 0;
}
if(lv>rv)
{
return 0;
}
if(l==r)
{
if(a[l]>=lv&&a[l]<=rv)
{
return 1;
}
return 0;
}
int Res=dfs(l+1,r,lv,rv);
if(a[l]>=lv&&a[l]<=rv)
{
for(int k=l;k<=r;k++)
{
Res=max(Res,1+dfs(l+1,k,lv,a[l])+dfs(k+1,r,a[l],rv));
}
}
dp[l][r][lv][rv]=Res;
return Res;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(1,n,1,50));
}
ABC262Ex
很典??
不难发现处理出每个点能取到的最大值\(V_i\),单独把\(V_i\)相同的拉出来搞
然后这个问题相当于有若干条限制\([l_i,r_i]\),和若干个点,你可以染色使得每个区间都有染色点
把每个限制放在最后考虑,设\(dp_{i,j}\)表示前\(i\)个点前面第一个被染色的为\(j\)
考虑\(i\)为右端点时的区间左端点最大值为\(h_i\)
则\(h_i\le j\le i\)
直接线段树维护一下即可
Show Code
#include<bits/stdc++.h>
#define ls p<<1
#define rs (p<<1)|1
using namespace std;
const int MAXN=4e5+5;
const int MOD=998244353;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int T;
int n,Q,A;
int l[MAXN],r[MAXN],m[MAXN];
int lshv[MAXN];
int lsh[MAXN];
int fa[MAXN];
int find(int x)
{
if(fa[x]==x)
{
return fa[x];
}
fa[x]=find(fa[x]);
return fa[x];
}
void unionn(int i,int j)
{
fa[find(i)]=find(j);
}
vector<int>V[MAXN];
vector<int>Rec[MAXN];
int vis[MAXN];
struct Seg{
int date;
int l,r;
int lazy;
}Tree[MAXN*4];
int f[MAXN];
void push_down(int p)
{
if(Tree[p].lazy)
{
Tree[ls].date=0;
Tree[rs].date=0;
Tree[ls].lazy=1;
Tree[rs].lazy=1;
Tree[p].lazy=0;
}
}
void push_up(int p)
{
Tree[p].date=((long long)Tree[ls].date+Tree[rs].date)%MOD;
}
void Build(int p,int l,int r)
{
// cerr<<"p"<<endl;
Tree[p].l=l;
Tree[p].r=r;
Tree[p].lazy=0;
if(l==r)
{
Tree[p].date=0;
return;
}
int mid=(l+r)>>1;
Build(ls,l,mid);
Build(rs,mid+1,r);
push_up(p);
}
void Update(int p,int l,int r)
{
//cerr<<"p"<<endl;
if(l>r)
{
return;
}
if(Tree[p].l>=l&&Tree[p].r<=r)
{
Tree[p].date=0;
Tree[p].lazy=1;
return;
}
push_down(p);
int mid=(Tree[p].l+Tree[p].r)>>1;
if(l<=mid)
{
Update(ls,l,r);
}
if(r>mid)
{
Update(rs,l,r);
}
push_up(p);
}
void Insert(int p,int k,int x)
{
//cerr<<"p"<<endl;
if(Tree[p].l==Tree[p].r)
{
Tree[p].date=x;
return;
}
push_down(p);
int mid=(Tree[p].l+Tree[p].r)>>1;
if(k<=mid)
{
Insert(ls,k,x);
}
else
{
Insert(rs,k,x);
}
push_up(p);
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
T=1;
while(T--)
{
scanf("%d %d %d",&n,&A,&Q);
A++;
int cntv=0,cnt=0;
for(int i=1;i<=Q;i++)
{
scanf("%d %d %d",&l[i],&r[i],&m[i]);
m[i]++;
lshv[++cntv]=m[i];
lsh[++cnt]=l[i];
lsh[++cnt]=r[i]+1;
}
sort(lshv+1,lshv+1+cntv);
cntv=unique(lshv+1,lshv+1+cntv)-lshv-1;
for(int i=1;i<=cntv;i++)
{
V[i].clear();
}
lsh[++cnt]=1;
lsh[++cnt]=n+1;
sort(lsh+1,lsh+1+cnt);
cnt=unique(lsh+1,lsh+1+cnt)-lsh-1;
for(int i=1;i<=Q;i++)
{
l[i]=lower_bound(lsh+1,lsh+1+cnt,l[i])-lsh;
r[i]=lower_bound(lsh+1,lsh+1+cnt,r[i]+1)-lsh-1;
m[i]=lower_bound(lshv+1,lshv+1+cntv,m[i])-lshv;
V[m[i]].push_back(i);
}
for(int i=1;i<=cnt+1;i++)
{
fa[i]=i;
vis[i]=0;
}
int Res=1;
for(int i=1;i<=cntv;i++)
{
vector<int>Used;
//cerr<<i<<endl;
for(int j=0;j<V[i].size();j++)
{
int id=V[i][j];
int Now=find(l[id]);
//printf("%d %d\n",l[id],r[id]);
while(Now<=r[id])
{
if(!vis[Now])
{
vis[Now]=1;
Used.push_back(Now);
}
int to=find(Now+1);
//cerr<<"fu"<<endl;
unionn(Now,to);
Now=to;
}
}
sort(Used.begin(),Used.end());
for(int j=0;j<Used.size();j++)
{
Rec[j].clear();
}
for(int j=0;j<V[i].size();j++)
{
int id=V[i][j];
int L=lower_bound(Used.begin(),Used.end(),l[id])-Used.begin();
int R=upper_bound(Used.begin(),Used.end(),r[id])-Used.begin()-1;
if(L>R)
{
Res=0;
break;
}
Rec[R].push_back(L);
//printf("%d %d\n",L,R);
}
f[0]=1;
Build(1,0,Used.size());
Insert(1,0,1);
int Mul=1;
for(int j=1;j<=Used.size();j++)
{
if(lshv[i]>1)
{
int v=lsh[Used[j-1]+1]-lsh[Used[j-1]];
Mul=((long long)Mul*Pow(lshv[i]-1,v,MOD)%MOD);
int H=0;
for(int k=0;k<Rec[j-1].size();k++)
{
int p=Rec[j-1][k];
H=max(H,p+1);
}
Update(1,0,H-1);
int xks=((long long)f[j-1]*(((long long)Pow(lshv[i],v,MOD)-Pow(lshv[i]-1,v,MOD)+MOD)%MOD))%MOD;
xks=((long long)xks*inv(Mul,MOD))%MOD;
Insert(1,j,xks);
f[j]=((long long)Tree[1].date*Mul)%MOD;
}
else
{
f[j]=1;
}
}
//printf("%d %d??\n",f[Used.size()],Used.size());
Res=((long long)Res*f[Used.size()])%MOD;
}
int tot=0;
for(int i=1;i<cnt;i++)
{
if(find(i)==i)
{
tot+=lsh[i+1]-lsh[i];
}
}
Res=((long long)Res*Pow(A,tot,MOD))%MOD;
printf("%d\n",Res);
}
}
ABC261G
有趣的半屉?
首先有一个不大成熟的思路是我们考虑求出\(f_{c,l,r}\)为用字符\(c\)得到\([l,r]\)的最小代价
这个\(f_{c,l,r}\)我们考虑把它分为若干个段求解,如果直接枚举每条边求解里面跑\(dp\)复杂度大概是\(26\times 50^5\)
这里再设\(g_{l,r,k,i}\)表示用第\(k\)个关系的前\(i\)个字符能得到\([l,r]\)的最小代价
这样似乎就可以转移了
有个问题,单个字符之间的转移时有问题的,因为没有后效性
因此我们在单个字符之间要跑一次\(floyd\)
Show Code
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
string t,tmp;
int dis[27][27];
vector<int>G[27];
string v[55];
int f[27][55][55];
int g[55][55][55][55];
int dp[55][55];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
cin>>s;
cin>>t;
scanf("%d",&n);
memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=n;i++)
{
cin>>tmp;
cin>>v[i];
G[tmp[0]-'a'+1].push_back(i);
if(v[i].size()==1)
{
dis[v[i][0]-'a'+1][tmp[0]-'a'+1]=1;
}
}
for(int k=1;k<=26;k++)
{
for(int i=1;i<=26;i++)
{
for(int j=1;j<=26;j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
int m=t.size();
memset(f,0x3f,sizeof(f));
memset(g,0x3f,sizeof(g));
for(int j=0;j<m;j++)
{
f[t[j]-'a'+1][j][j]=0;
}
for(int p=0;p<m;p++)
{
for(int k=1;k<=26;k++)
{
for(int i=1;i<=26;i++)
{
for(int j=1;j<=26;j++)
{
f[i][p][p]=min(f[i][p][p],f[j][p][p]+dis[j][i]);
}
}
}
}
for(int j=0;j<m;j++)
{
for(int i=1;i<=n;i++)
{
g[j][j][i][0]=f[v[i][0]-'a'+1][j][j];
}
}
//printf("%d %d")
//printf("%d %d %d %d %d %d::\n",f[2][1][1],t[2]-'a'+1,g[0][0][2][0],f[1][1][1],dis[2][1]);
for(int len=2;len<=m;len++)
{
for(int l=0;l+len-1<m;l++)
{
int r=l+len-1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<v[i].size();j++)
{
for(int k=l;k<r;k++)
{
g[l][r][i][j]=min(g[l][r][i][j],g[l][k][i][j-1]+f[v[i][j]-'a'+1][k+1][r]);
}
}
}
//printf("%d %d %d---------\n",f[2][1][1],t[2]-'a'+1,g[0][1][2][1]);
for(int i=1;i<=26;i++)
{
for(int j=0;j<G[i].size();j++)
{
int vw=G[i][j];
f[i][l][r]=min(f[i][l][r],g[l][r][vw][v[vw].size()-1]+1);
}
}
// for(int k=1;k<=26;k++)
// {
// for(int i=1;i<=26;i++)
// {
// for(int j=1;j<=26;j++)
// {
// f[i][l][r]=min(f[i][l][r],f[j][l][r]+dis[j][i]);
// }
// }
// }
// for(int i=1;i<=n;i++)
// {
// g[l][r][i][0]=f[v[i][0]-'a'+1][l][r];
// }//只有一个可以互相转移
// for(int i=1;i<=26;i++)
// {
// if(f[i][l][r]!=0x3f3f3f3f)
// {
// printf("%d %d %d %d::\n",i,l,r,f[i][l][r]);
// }
// }
}
}
// printf("%d %d %d %d %d??\n",g[0][0][20][0],f['n'-'a'+1][0][0],f['n'-'a'+1][0][1],f['n'-'a'+1][1][1],g[0][1][20][1]);
//printf("%d::\n",f[1][1][1]);
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=t.size();i++)
{
for(int j=1;j<=s.size();j++)
{
for(int k=0;k<i;k++)
{
dp[i][j]=min(dp[i][j],dp[k][j-1]+f[s[j-1]-'a'+1][k][i-1]);
}
}
}
if(dp[t.size()][s.size()]==0x3f3f3f3f)
{
printf("-1\n");
}
else
{
printf("%d\n",dp[t.size()][s.size()]);
}
}
ABC261Ex
脑袋被僵尸吃了/kk
和省选那题极度相似
解释一下为啥最大值是这样
因为对于\(1\),当前更新出度为\(0\)的它是一个都不想走,只想走到环上
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,m;
int x,y,z;
struct Edge{
int v,val;
};
vector<Edge>g[MAXN];
long long dp[MAXN][2];
int vis[MAXN][2];
int rd[MAXN];
int k;
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
g[y].push_back((Edge){x,z});
rd[x]++;
}
priority_queue<pair<long long,pair<int,int> > >Q;
for(int i=1;i<=n;i++)
{
dp[i][0]=2e18;
dp[i][1]=0;
}
for(int i=1;i<=n;i++)
{
if(!rd[i])
{
Q.push(make_pair(0,make_pair(i,0)));
Q.push(make_pair(0,make_pair(i,1)));
dp[i][0]=dp[i][1]=0;
}
}
while(Q.size())
{
auto it=Q.top().second;
Q.pop();
if(vis[it.first][it.second])
{
continue;
}
vis[it.first][it.second]=1;
for(int i=0;i<g[it.first].size();i++)
{
int v=g[it.first][i].v;
int w=g[it.first][i].val;
if(it.second==0)
{
dp[v][1]=max(dp[v][1],dp[it.first][0]+w);
rd[v]--;
if(!rd[v])
{
Q.push(make_pair(-dp[v][1],make_pair(v,1)));
}
}
else
{
dp[v][0]=min(dp[v][0],dp[it.first][1]+w);
Q.push(make_pair(-dp[v][0],make_pair(v,0)));
}
}
}
if(vis[k][0])
{
printf("%lld\n",dp[k][0]);
}
else
{
printf("INFINITY");
}
}
ABC260G
nt差分,调了一下午自闭了
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=9005;
int n,m,q;
int x,y;
char mp[MAXN][MAXN];
int cf1[MAXN][MAXN];
int cf2[MAXN][MAXN];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
}
m=2*m-1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(mp[i][j]=='O')
{
int x=2*i-1;
int y=j;
cf1[x][y]++;
if(y+m+1<=MAXN-5)
{
cf1[x][y+m+1]--;
cf2[x][y+m+1]++;
}
if(x+m+1<=MAXN-5)
{
cf2[x+m+1][y]--;
}
}
}
}
// for(int i=1;i<=5;i++)
// {
// for(int j=1;j<=5;j++)
// {
// printf("%5d",cf2[i][j]);
// }
// printf("\n");
// }
// printf("\n");
for(int i=MAXN-5;i>=1;i--)
{
for(int j=1;j<=MAXN-5;j++)
{
cf2[i][j]+=cf2[i+1][j-1];
}
}
// for(int i=1;i<=5;i++)
// {
// for(int j=1;j<=5;j++)
// {
// printf("%5d",cf2[i][j]);
// }
// printf("\n");
// }
// printf("\n");
for(int i=1;i<=MAXN-5;i++)
{
for(int j=1;j<=MAXN-5;j++)
{
cf1[i][j]=cf1[i][j]+cf1[i][j-1];
}
}
for(int i=1;i<=MAXN-5;i++)
{
for(int j=1;j<=MAXN-5;j++)
{
cf1[i][j]=cf1[i][j]+cf2[i][j];
}
}
// for(int i=1;i<=5;i++)
// {
// for(int j=1;j<=5;j++)
// {
// printf("%5d",cf1[i][j]);
// }
// printf("\n");
// }
for(int i=1;i<=MAXN-5;i++)
{
for(int j=1;j<=MAXN-5;j++)
{
cf1[i][j]=cf1[i][j]+cf1[i-1][j];
}
}
scanf("%d",&q);
while(q--)
{
scanf("%d %d",&x,&y);
printf("%d\n",cf1[2*x-1][y]);
}
}
ABC259G
和文理分科差不多的玩意,好像吧
Show Code
#include<bits/stdc++.h>
#define int long long
#define INF 2e18
using namespace std;
const int MAXN=405;
struct Edge{
int to,val,nxt;
}edge[MAXN*MAXN*10];
int cnt_edge=1;
int head[MAXN*10];
void Add(int u,int v,int val)
{
edge[++cnt_edge].val=val;
edge[cnt_edge].nxt=head[u];
edge[cnt_edge].to=v;
head[u]=cnt_edge;
}
void add(int u,int v,int val)
{
Add(u,v,val);
Add(v,u,0);
}
int S,T;
int dis[MAXN*10];
int arc[MAXN*10];
int bfs()
{
queue<int>q;
q.push(S);
for(int i=S;i<=T;i++)
{
dis[i]=-1;
}
dis[S]=0;
while(q.size())
{
int u=q.front();
q.pop();
arc[u]=head[u];
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
int w=edge[i].val;
if(!w)
{
continue;
}
if(dis[v]!=-1)
{
continue;
}
dis[v]=dis[u]+1;
q.push(v);
}
}
return dis[T]!=-1;
}
int dfs(int x,int Cap)
{
if(x==T)
{
return Cap;
}
if(Cap==0)
{
return Cap;
}
//cerr<<x<<endl;
int Used=0;
for(int i=arc[x];i;i=edge[i].nxt)
{
arc[x]=i;
int v=edge[i].to;
int w=edge[i].val;
if(dis[v]==dis[x]+1)
{
if(!w)
{
continue;
}
int cap=dfs(v,min(w,Cap));
Cap-=cap;
Used+=cap;
edge[i].val-=cap;
edge[i^1].val+=cap;
if(Cap==0)
{
break;
}
}
}
return Used;
}
int dinic()
{
int Maxflow=0;
while(bfs())
{
int Flow;
while((Flow=dfs(S,INF)))
{
Maxflow+=Flow;
}
}
return Maxflow;
}
int n,m;
int a[MAXN][MAXN];
signed main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%lld %lld",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%lld",&a[i][j]);
}
}
S=0;
T=n+m+1;
long long Res=0;
for(int i=1;i<=n;i++)
{
long long Sum=0;
for(int j=1;j<=m;j++)
{
Sum+=a[i][j];
}
if(Sum>0)
{
add(S,i,Sum);
Res+=Sum;
}
}
for(int i=1;i<=m;i++)
{
long long Sum=0;
for(int j=1;j<=n;j++)
{
Sum+=a[j][i];
}
if(Sum>0)
{
add(i+n,T,Sum);
Res+=Sum;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]>=0)
{
add(i,j+n,a[i][j]);
}
else
{
add(i,j+n,INF);
}
}
}
// printf("%lld\n",Res);
// for(int i=S;i<=T;i++)
// {
// for(int j=head[i];j;j=edge[j].nxt)
// {
// if(edge[j].val)
// {
// printf("%d %d %d\n",i,edge[j].to,edge[j].val);
// }
// }
// }
printf("%lld\n",Res-dinic());
}
ABC258Ex
zz矩乘,一直往容斥的方向想,真小丑
Show Code
// LUOGU_RID: 135388999
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const int MOD=998244353;
long long S;
int n;
long long a[MAXN];
struct Martix{
int val[3][3];
void clear()
{
memset(val,0,sizeof(val));
}
void init()
{
clear();
for(int i=0;i<=2;i++)
{
val[i][i]=1;
}
}
Martix operator*(const Martix x)const{
Martix Res;
Res.clear();
for(int k=0;k<=2;k++)
{
for(int i=0;i<=2;i++)
{
for(int j=0;j<=2;j++)
{
Res.val[i][j]=((long long)Res.val[i][j]+((long long)val[i][k]*x.val[k][j])%MOD)%MOD;
}
}
}
return Res;
}
}A,B;
Martix Pow(Martix a,long long b)
{
Martix res;
res.init();
while(b)
{
if(b&1)
{
res=res*a;
}
a=a*a;
b>>=1;
}
return res;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %lld",&n,&S);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
Martix Res;
Res.clear();
Res.val[0][0]=1;
Res.val[0][1]=1;
Res.val[0][2]=0;
A.val[0][0]=0;A.val[0][1]=0;A.val[0][2]=0;
A.val[1][0]=1;A.val[1][1]=1;A.val[1][2]=1;
A.val[2][0]=0;A.val[2][1]=1;A.val[2][2]=0;
B.val[0][0]=0;B.val[0][1]=0;B.val[0][2]=0;
B.val[1][0]=0;B.val[1][1]=0;B.val[1][2]=1;
B.val[2][0]=0;B.val[2][1]=1;B.val[2][2]=0;
for(int i=1;i<=n;i++)
{
long long d=a[i]-a[i-1]-1;
Res=Res*Pow(A,d);
Res=Res*B;
}
Res=Res*Pow(A,S-a[n]);
printf("%d",Res.val[0][0]);
}
ABC256G
zz矩乘
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=1e4+5;
int D;
long long n;
struct Martix{
int val[2][2];
void clear()
{
memset(val,0,sizeof(val));
}
void init()
{
clear();
for(int i=0;i<=1;i++)
{
val[i][i]=1;
}
}
Martix operator*(const Martix x)const{
Martix Res;
Res.clear();
for(int k=0;k<=1;k++)
{
for(int i=0;i<=1;i++)
{
for(int j=0;j<=1;j++)
{
Res.val[i][j]=((long long)Res.val[i][j]+((long long)val[i][k]*x.val[k][j])%MOD)%MOD;
}
}
}
return Res;
}
}A;
int Pow(int a,int b,int p)
{
int res=1;
int base=a;
while(b)
{
if(b&1)
{
res=((long long)res*base)%p;
}
base=((long long)base*base)%p;
b>>=1;
}
return res;
}
int inv(int a,int p)
{
return Pow(a,p-2,p);
}
int fac[MAXN];
int inv_fac[MAXN];
int C(int n,int m)
{
if(n<m||m<0)
{
return 0;
}
if(n==m||m==0)
{
return 1;
}
//printf("%d %d %d:::\n",n,m,((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD);
return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}
Martix Pw(Martix a,long long b)
{
Martix res;
res.init();
while(b)
{
if(b&1)
{
res=res*a;
}
a=a*a;
b>>=1;
}
return res;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
fac[0]=1;
for(int i=1;i<=MAXN-5;i++)
{
fac[i]=((long long)fac[i-1]*i)%MOD;
}
inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
for(int i=MAXN-5-1;i>=1;i--)
{
inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
}
scanf("%lld %d",&n,&D);
int Res=0;
D++;
for(int i=0;i<=D;i++)
{
A.val[0][0]=C(D-2,i);A.val[0][1]=C(D-2,i-1);
A.val[1][0]=C(D-2,i-1);A.val[1][1]=C(D-2,i-2);
A=Pw(A,n);
Res=((long long)Res+A.val[0][0])%MOD;
Res=((long long)Res+A.val[1][1])%MOD;
// printf("%d %d %d??\n",i,A.val[0][0],A.val[1][1]);
}
printf("%d\n",Res);
}
ABC255G
求SG,手完一下,直接处理特殊点,其他点依次平移
特殊点删除有点麻烦,注意到我们可以直接处理出需要用到\(sg\)的个数即可
Show Code
// LUOGU_RID: 135443779
#include<bits/stdc++.h>
using namespace std;
const int MAXN=6e5+5;
int n,m;
long long a[MAXN];
map<long long,int>Vis;
long long x,y;
vector<long long>g[MAXN];
long long Sg[MAXN];
map<long long,int>Num;
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%d %d",&n,&m);
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(!Vis[a[i]])
{
Vis[a[i]]=++cnt;
}
}
for(int i=1;i<=m;i++)
{
scanf("%lld %lld",&x,&y);
if(!Vis[x])
{
Vis[x]=++cnt;
}
if(!Vis[x-y])
{
Vis[x-y]=++cnt;
}
g[Vis[x]].push_back(Vis[x-y]);
}
int del=0;
for(auto it=Vis.begin();it!=Vis.end();it++)
{
auto tmp=(*it);
Sg[tmp.second]=tmp.first-del;
for(int j=0;j<g[tmp.second].size();j++)
{
int v=g[tmp.second][j];
Num[Sg[v]]--;
if(!Num[Sg[v]])
{
Sg[tmp.second]=min(Sg[tmp.second],Sg[v]);
}
}
for(int j=0;j<g[tmp.second].size();j++)
{
int v=g[tmp.second][j];
Num[Sg[v]]++;
}
Num[Sg[tmp.second]]++;
if(Sg[tmp.second]!=tmp.first-del)
{
del++;
}
// printf("%lld %lld\n",tmp.first,Sg[tmp.second]);
}
long long sx=0;
for(int i=1;i<=n;i++)
{
sx^=Sg[Vis[a[i]]];
}
if(sx)
{
printf("Takahashi");
}
else
{
printf("Aoki");
}
}
ABC255Ex
线段树半屉
Show Code
// LUOGU_RID: 135457847
#include<bits/stdc++.h>
#define ls p<<1
#define rs (p<<1)|1
using namespace std;
const int MOD=998244353;
const int MAXN=4e5+5;
const int inv2=MOD-MOD/2;
int Q;
long long n;
struct Qry{
long long D,l,r;
}qur[MAXN];
long long D,l,r;
long long lsh[MAXN];
struct Seg{
int lazy1;
int lazy2;
int l,r;
int sd;
}Tree[MAXN*4];
void push_down(int p)
{
if(Tree[p].lazy1)
{
Tree[ls].lazy1=1;
Tree[ls].sd=0;
Tree[ls].lazy2=0;
Tree[rs].lazy1=1;
Tree[rs].sd=0;
Tree[rs].lazy2=0;
Tree[p].lazy1=0;
}
if(Tree[p].lazy2)
{
Tree[ls].lazy2=((long long)Tree[ls].lazy2+Tree[p].lazy2)%MOD;
int Amx=(lsh[Tree[ls].r+1]-1+lsh[Tree[ls].l])%MOD;
Amx=((long long)Amx*(((lsh[Tree[ls].r+1]-lsh[Tree[ls].l]))%MOD))%MOD;
Amx=((long long)Amx*inv2)%MOD;
Amx=((long long)Amx*Tree[p].lazy2)%MOD;
Tree[ls].sd=((long long)Tree[ls].sd+Amx)%MOD;
Tree[rs].lazy2=((long long)Tree[rs].lazy2+Tree[p].lazy2)%MOD;
Amx=(lsh[Tree[rs].r+1]-1+lsh[Tree[rs].l])%MOD;
Amx=((long long)Amx*(((lsh[Tree[rs].r+1]-lsh[Tree[rs].l]))%MOD))%MOD;
Amx=((long long)Amx*inv2)%MOD;
Amx=((long long)Amx*Tree[p].lazy2)%MOD;
Tree[rs].sd=((long long)Tree[rs].sd+Amx)%MOD;
Tree[p].lazy2=0;
}
}
void push_up(int p)
{
Tree[p].sd=((long long)Tree[ls].sd+Tree[rs].sd)%MOD;
}
void Build(int p,int l,int r)
{
Tree[p].l=l;
Tree[p].r=r;
Tree[p].lazy1=0;
Tree[p].lazy2=0;
if(l==r)
{
Tree[p].sd=0;
return;
}
int mid=(l+r)>>1;
Build(ls,l,mid);
Build(rs,mid+1,r);
push_down(p);
}
void Update1(int p,int l,int r)
{
if(Tree[p].l>=l&&Tree[p].r<=r){
Tree[p].sd=0;
Tree[p].lazy1=1;
Tree[p].lazy2=0;
return;
}
int mid=(Tree[p].l+Tree[p].r)>>1;
push_down(p);
if(l<=mid)
{
Update1(ls,l,r);
}
if(r>mid)
{
Update1(rs,l,r);
}
push_up(p);
}
void Update2(int p,int l,int r,int x)
{
if(Tree[p].l>=l&&Tree[p].r<=r)
{
int Amx;
Tree[p].lazy2=((long long)Tree[p].lazy2+x)%MOD;
Amx=(lsh[Tree[p].r+1]-1+lsh[Tree[p].l])%MOD;
Amx=((long long)Amx*(((lsh[Tree[p].r+1]-lsh[Tree[p].l]))%MOD))%MOD;
Amx=((long long)Amx*inv2)%MOD;
Amx=((long long)Amx*x)%MOD;
Tree[p].sd=((long long)Tree[p].sd+Amx)%MOD;
//printf("%d %d %d::\n",Tree[p].l,Tree[p].r,Tree[p].sd);
return;
}
push_down(p);
int mid=(Tree[p].l+Tree[p].r)>>1;
if(l<=mid)
{
Update2(ls,l,r,x);
}
if(r>mid)
{
Update2(rs,l,r,x);
}
push_up(p);
}
int Query(int p,int l,int r)
{
if(Tree[p].l>=l&&Tree[p].r<=r)
{
return Tree[p].sd;
}
int mid=(Tree[p].l+Tree[p].r)>>1;
push_down(p);
// printf("%d %d %d::\n",Tree[ls].l,Tree[ls].r,Tree[ls].sd);
// printf("%d %d %d::\n",Tree[rs].l,Tree[rs].r,Tree[rs].sd);
int Res=0;
if(l<=mid)
{
Res=((long long)Res+Query(ls,l,r))%MOD;
}
if(r>mid)
{
Res=((long long)Res+Query(rs,l,r))%MOD;
}
return Res;
}
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
scanf("%lld",&n);
scanf("%d",&Q);
int Cnt=0;
for(int i=1;i<=Q;i++)
{
scanf("%lld %lld %lld",&D,&l,&r);
qur[i]=(Qry{D,l,r});
lsh[++Cnt]=l;
lsh[++Cnt]=r+1;
}
sort(lsh+1,lsh+1+Cnt);
Cnt=unique(lsh+1,lsh+1+Cnt)-lsh-1;
Build(1,1,Cnt-1);
long long L=0;
for(int i=1;i<=Q;i++)
{
D=qur[i].D;
l=qur[i].l;
r=qur[i].r;
l=lower_bound(lsh+1,lsh+1+Cnt,l)-lsh;
r=lower_bound(lsh+1,lsh+1+Cnt,r+1)-lsh-1;
Update2(1,1,Cnt-1,(D-L)%MOD);
//printf("%d %d::\n",l,r);
int S=Query(1,l,r);
Update1(1,l,r);
printf("%d\n",S);
L=D;
}
}
[ABC280Ex] Substring Sort
codechef春春贵物,还得看AT
后缀树半屉
Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+6;
void read(long long &x)
{
x=0;
int f=1;
char s=getchar();
while(s<'0'||s>'9')
{
s=getchar();
}
while(s>='0'&&s<='9')
{
x=x*10+(s-'0');
s=getchar();
}
return;
}
int n;
string S[MAXN];
struct SAM{
int len,link;
int num;
int nxt[26];
pair<int,int> col;
}Tree[MAXN*2];
int cnt_node;
void Build()
{
Tree[0].link=-1;
return;
}
int las;
int Insert(char s,int Pos,int id)
{
int cur=++cnt_node;
int p=las;
Tree[cur].len=Tree[p].len+1;
while((p!=-1)&&(!Tree[p].nxt[s-'a']))
{
//printf("%d %d??\n",p);
Tree[p].nxt[s-'a']=cur;
p=Tree[p].link;
}
//printf("%d %d %d??\n",Tree[1].nxt[0],las,Tree[1].link);
if(p==-1)
{
Tree[cur].link=0;
}
else
{
int q=Tree[p].nxt[s-'a'];
if(Tree[q].len!=Tree[p].len+1)
{
int clone=++cnt_node;
Tree[clone].link=Tree[q].link;
Tree[clone].len=Tree[p].len+1;
for(int i=0;i<26;i++)
{
Tree[clone].nxt[i]=Tree[q].nxt[i];
}
Tree[cur].link=clone;
Tree[q].link=clone;
while((p!=-1)&&(Tree[p].nxt[s-'a']==q))
{
Tree[p].nxt[s-'a']=clone;
p=Tree[p].link;
}
}
else
{
Tree[cur].link=q;
}
}
Tree[cur].col=make_pair(id,Pos);
Tree[cur].num=1;
//printf("%d %d??\n",Pos,cur);
return cur;
}
vector<int>g[MAXN*2];
void dfs1(int x)
{
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
dfs1(v);
Tree[x].col=Tree[v].col;
}
}
int cmp(int x,int y)
{
return S[Tree[x].col.first][Tree[x].col.second+Tree[Tree[x].link].len-1]<S[Tree[y].col.first][Tree[y].col.second+Tree[Tree[y].link].len-1];
}
int cnt_dfn;
int dfn[MAXN*2];
int Rlf[MAXN*2];
int dp[MAXN*2][22];
void dfs2(int x)
{
sort(g[x].begin(),g[x].end(),cmp);
Rlf[++cnt_dfn]=x;
dfn[x]=cnt_dfn;
if(x)
{
dp[x][0]=Tree[x].link;
for(int j=1;j<=20;j++)
{
dp[x][j]=dp[dp[x][j-1]][j-1];
}
}
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
dfs2(v);
Tree[x].num+=Tree[v].num;
}
}
int q;
long long Q[MAXN];
int main()
{
// freopen("date.in","r",stdin);
// freopen("date.out","w",stdout);
Build();
scanf("%d",&n);
for(int j=1;j<=n;j++)
{
las=0;
cin>>S[j];
reverse(S[j].begin(),S[j].end());
for(int i=0;i<S[j].size();i++)
{
las=Insert(S[j][i],(int)S[j].size()-i,j);
}
reverse(S[j].begin(),S[j].end());
}
for(int i=1;i<=cnt_node;i++)
{
//printf("%d %d\n",Tree[i].link,i);
g[Tree[i].link].push_back(i);
}
dfs1(0);
dfs2(0);
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%lld",&Q[i]);
}
long long Noi=0;
int Pi=1;
for(int i=1;i<=cnt_dfn;i++)
{
if(!Rlf[i])
{
continue;
}
int x=Rlf[i];
int Len=(Tree[x].len-Tree[Tree[x].link].len);
while(Pi<=q&&(Q[Pi]<=Noi+((long long)Len*Tree[x].num)))
{
long long Res=Q[Pi]-Noi;
Res=((Res-1)/(Tree[x].num))+1;
int Lx=Tree[Tree[x].link].len+Res;
printf("%d %d %d\n",Tree[x].col.first,Tree[x].col.second,Tree[x].col.second+Lx-1);
++Pi;
}
Noi+=((long long)Len*Tree[x].num);
}
// printf("%lld %d",Noi,Q[q]);
}