1. 程式人生 > 其它 >21牛客多校第三場

21牛客多校第三場

這場好難 \(dls\)下手也太狠了

A

好奇怪的題 棄了

B

將每個點認為是邊和列之間的邊,容易發現題意即為求最小生成樹

因為邊權不會太大,桶排序後\(kruskal\)即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%p
#define mul(a,b) (1LL*(a)*(b))%p
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,a,b,c,d,p,las,fa[MAXN],ans;
vector<pii> e[MAXN];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
inline int merge(int u,int v)
{
	int fu=find(u),fv=find(v);
	if(fu!=fv) return fa[fu]=fv;return 0;
}
int main()
{
	n=read(),m=read(),las=a=read(),b=read(),c=read(),d=read(),p=read();
	rep(i,1,n) rep(j,1,m)
	{
		las=pls(pls(mul(mul(las,las),b),mul(las,c)),d);
		e[las].pb({i,j+n});
	}
	rep(i,1,n+m) fa[i]=i;
	rep(i,0,p-1) for(auto t:e[i])
		if(merge(t.fi,t.se)) ans+=i;
	printf("%d\n",ans);
}

C

至多\(2n\)個點就一定可以滿足要求,而能減小答案的點一定滿足該點所在行和列限制相同

這樣的話對於這種點行與列連邊,做最大費用流即可

#include<bits/stdc++.h>
#define inf 213906214300000LL
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 1001001
#define MAXM 1001001
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,k,a[MAXN],b[MAXN];
ll ans;
struct ZKW
{
	int nxt[MAXM<<1],to[MAXM<<1],val[MAXM<<1],cnt,fst[MAXN];
	int vis[MAXN],S,T;queue<int> q;
	ll cst[MAXM<<1],dis[MAXN],res;
	void mem(){Fill(fst,0);cnt=1,res=0;}
	void add(int u,int v,int w,int c) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w,cst[cnt]=c;}
	void ins(int u,int v,int w,int c) {add(u,v,w,c),add(v,u,0,-c);}
	int spfa()
	{
		int x;rep(i,1,n*2+2) dis[i]=-inf,vis[i]=0;
		dis[T]=0,vis[T]=1;q.push(T);while(!q.empty())
		{
			x=q.front(),q.pop();vis[x]=0;ren if(dis[to[i]]<dis[x]-cst[i]&&val[i^1])
				{dis[to[i]]=dis[x]-cst[i];if(!vis[to[i]]) vis[to[i]]=1,q.push(to[i]);}
		}
		return dis[S]!=-inf;
	}
	int dfs(int x,int a)
	{
		if(vis[x]) return 0;vis[x]=1;if(x==T||!a) {res+=a*dis[S];return a;}
		int f,flw=0;ren if(val[i]&&dis[to[i]]==dis[x]-cst[i]&&(f=dfs(to[i],min(a,val[i]))))
			a-=f,val[i]-=f,val[i^1]+=f,flw+=f;
		return flw;
	}
	int solve()
	{
		int f,flw=0;while(spfa()) 
			do{memset(vis,0,sizeof(vis));f=dfs(S,inf),flw+=f;}while(f);
		return res;
	}
}Z;
int main()
{
	n=read(),m=read(),k=read();int x,y;
	rep(i,1,n) a[i]=read(),ans+=a[i];
	rep(i,1,n) b[i]=read(),ans+=b[i];
	Z.mem();Z.S=2*n+1,Z.T=2*n+2;
	rep(i,1,n) Z.ins(Z.S,i,1,0),Z.ins(n+i,Z.T,1,0);
	rep(i,1,m) {x=read(),y=read();if(a[x]==b[y]) Z.ins(x,y+n,1,a[x]);}
	printf("%d\n",ans-Z.solve());
}

D

容斥+三維揹包 咕了

E

打表題(bushi

不難發現每一對數對是連續的,且\(a_i=x^2 a_{i-1}-a_{i-2}\),其中\((x,x^3)\)為這一條鏈的起始數對

最後\(upper\_bound\)即可

(也可以正經做,但是懶得再推一遍了,反正結論就是這個

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

F

爆搜題

可以發現\(n\le 3\)時顯然不可能所有操作出現分數,直接判斷

先搜出\(4\)個數的組合,再排列後列舉所有的符號組合

判斷能湊出答案的所有方案是否都出現分數即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const db eps=1e-6;
int n,m,op[10],p,w[10],res=0;
vector<int> ans[5];
inline int isz(db x){return (-eps<x&&x<eps);}
int isd(db x){return fabs(x-(int)x)>=eps;}
db calc(db a,db b,int c)
{
	if(c==1) return a+b;
	if(c==2) return a-b;
	if(c==3) return a*b;
	if(isz(b)) return inf;
	return a/b;
}
int cheq()
{
	int ret=0,rett=0;db res=0;
	if(p==1)
	{
		db t1=calc(w[1],w[2],op[1]);
		if(isz(t1-inf)){ret=0;return ret;}
		if(isd(t1)) rett=1;
		db t2=calc(t1,w[3],op[2]);
		if(isz(t2-inf)){ret=0;return ret;}
		if(isd(t2)) rett=1;
		res=calc(t2,w[4],op[3]);
		if(isz(res-m)) ret=1;
		else {ret=0;return ret;}
	}
	else if(p==2)
	{
		db t1=calc(w[1],w[2],op[1]);
		if(isz(t1-inf)){ret=0;return ret;}
		if(isd(t1)) rett=1;
		db t2=calc(w[3],w[4],op[3]);
		if(isz(t2-inf)){ret=0;return ret;}
		if(isd(t2)) rett=1;
		res=calc(t1,t2,op[2]);
		if(isz(res-m)) ret=1;
		else {ret=0;return ret;}
	}
	else if(p==3)
	{
		db t1=calc(w[2],w[3],op[2]);
		if(isz(t1-inf)){ret=0;return ret;}
		if(isd(t1)) rett=1;
		db t2=calc(w[1],t1,op[1]);
		if(isz(t2-inf)){ret=0;return ret;}
		if(isd(t2)) rett=1;
		res=calc(t2,w[4],op[3]);
		if(isz(res-m)) ret=1;
		else {ret=0;return ret;}
	}
	else if(p==4)
	{
		db t1=calc(w[2],w[3],op[2]);
		if(isz(t1-inf)){ret=0;return ret;}
		if(isd(t1)) rett=1;
		db t2=calc(t1,w[4],op[3]);
		if(isz(t2-inf)){ret=0;return ret;}
		if(isd(t2)) rett=1;
		res=calc(w[1],t2,op[1]);
		if(isz(res-m)) ret=1;
		else {ret=0;return ret;}
	}
	else if(p==5)
	{
		db t1=calc(w[3],w[4],op[3]);
		if(isz(t1-inf)){ret=0;return ret;}
		if(isd(t1)) rett=1;
		db t2=calc(w[1],w[2],op[1]);
		if(isz(t2-inf)){ret=0;return ret;}
		if(isd(t2)) rett=1;
		res=calc(t1,t2,op[2]);
		if(isz(res-m)) ret=1;
		else {ret=0;return ret;}
	}
	else
	{
		db t1=calc(w[3],w[4],op[3]);
		if(isz(t1-inf)){ret=0;return ret;}
		if(isd(t1)) rett=1;
		db t2=calc(w[2],t1,op[2]);
		if(isz(t2-inf)){ret=0;return ret;}
		if(isd(t2)) rett=1;
		res=calc(w[1],t2,op[1]);
		if(isz(res-m)) ret=1;
		else {ret=0;return ret;}
	} 
	return ret+rett;
} 
void dfs2(int i,int &jud)
{
	if(!jud) return;
	if(i>n-1)
	{
		int ok=jud,flg;
		for(p=1;p<=6;++p)
		{
			flg=cheq();
			if(flg==1) ok=0;
			else if(flg==2&&ok) ok=1;
		}
		jud=ok;return;
	}
	rep(j,1,4){op[i]=j;dfs2(i+1,jud);}
}
void dfs(int i,int las)
{
	if(i>n)
	{
		int jud=-1;
		do {dfs2(1,jud);}
		while(next_permutation(w+1,w+n+1));
		if(jud>0) {res++;rep(j,1,n) ans[j].pb(w[j]);}
		return;
	}
	rep(j,las,13) {w[i]=j;dfs(i+1,j);}
	return;
}
int main()
{
	n=read(),m=read();if(n<=3) return puts("0"),0;
	dfs(1,1);printf("%d\n",res);
	rep(i,0,res-1) {rep(j,1,n) cout<<ans[j][i]<<" ";puts("");}
}

G

樹套樹 咕了

H

題解寫了3整頁 過於害怕於是棄了

I

\(0\)操作直接差分即可

對於\(1\)操作,先拆成\([l,n]\)\([r+1,n]\)兩段異或等差數列

容易發現對每一位來說,異或上的數一定是\(\dots11100001111\dots\)的一部分,連續\(2^i\)\(0/1\)交錯出現

因此在這一位上的所有修改的週期是一樣的,考慮二階差分

對於每個從\(t\)位置開始異或以\(x\)開始的等差數列,可以先將\(x\)加入到一階差分中

然後只需要找到每一位第一個和\(x\)不一樣的位置,每過\(2^i\)之後改變一次,放進二階差分中

最後先將二階差分陣列按週期性整合\(tag\),得到一階差分陣列,再直接求字首和即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 600100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,q,g[MAXN],s[MAXN];
bool tag[MAXN][30];
void work(int x,int w)
{
	s[x]^=w;rep(i,0,29)
	{
		int t=(((w>>i)+1)<<i)-w+x;
		if(t<=n) tag[t][i]^=1;
	}
}
int main()
{
	n=read(),q=read();rep(i,1,n) g[i]=read();int x,a,b;
	rep(i,1,q)
	{
		x=read();
		if(!x) {a=read(),b=read(),x=read();s[a]^=x,s[b+1]^=x;}
		else {a=read(),b=read(),x=read();work(a,x),work(b+1,x+b-a+1);}
	}
	rep(i,1,n) rep(j,0,29) if(tag[i][j])
	{
		s[i]^=(1<<j);
		if(i+(1<<j)<=n) tag[i+(1<<j)][j]^=1;
	}
	rep(i,1,n) {s[i]^=s[i-1];printf("%d%c",g[i]^s[i],i==n?'\n':' ');}
}

J

簽到題,同色三元環並不好計算,考慮計算異色三元環

異色三元環一定有兩個角是異色的,則只需統計有多少個異色角再

對每個點來說,異色角個數即 黑邊\(\times\)白邊

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
namespace GenHelper
{
    unsigned z1,z2,z3,z4,b,u;
    unsigned get()
    {
        b=((z1<<6)^z1)>>13;
        z1=((z1&4294967294U)<<18)^b;
        b=((z2<<2)^z2)>>27;
        z2=((z2&4294967288U)<<2)^b;
        b=((z3<<13)^z3)>>21;
        z3=((z3&4294967280U)<<7)^b;
        b=((z4<<3)^z4)>>12;
        z4=((z4&4294967168U)<<13)^b;
        return (z1^z2^z3^z4);
    }
    bool read() {
      while (!u) u = get();
      bool res = u & 1;
      u >>= 1; return res;
    }
    void srand(int x)
    {
        z1=x;
        z2=(~x)^0x233333333U;
        z3=x^0x1234598766U;
        z4=(~x)+51;
      	u = 0;
    }
}
using namespace GenHelper;
int n,seed,d[8080];
ll ans,res;
int main()
{
	cin>>n>>seed;srand(seed);int x;
	rep(i,1,n) rep(j,i+1,n) x=read(),d[i]+=x,d[j]+=x;
	ans=1LL*n*(n-1)*(n-2)/6;
	rep(i,1,n) ans-=1LL*d[i]*(n-1-d[i])/2;
	printf("%lld\n",ans);
}