Loading

CSP 后多校七

A. 谜之阶乘

签到题.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define int long long
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[]()->int{
		int w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:(-w);
	};
} using namespace BSS;

const int inf=1e18;

int m,n,cnt;
int ans[10][2];
auto calc=[](int x,int len,int res=1)->int{
	for(int i=1;i<=len;i++){
		if(res>(inf)/(i+x)) return -1;
		res=res*(i+x);
	}
	return res;
};
auto solve=[](int x,int len)->int{
	int l=1,r=pow(x,1.0/(1.0*len))+1,w,mid,res=-1;
	while(l<=r){
		mid=(l+r)>>1,w=calc(mid,len);
		if(w>=x or w<0) r=mid-1,res=mid;
		else l=mid+1;
	}
	return (calc(res,len)==x) ? res : -1 ;
};
auto Work=[]()->void{
	n=read(),cnt=0; int res;
	if(n==1) { puts("-1"); return ; }
	if(n==2) { puts("1"),puts("2 1"); return; }
	for(int i=20;i>=2;i--){
		res=solve(n,i);
		if(~res) ans[++cnt][0]=res+i,ans[cnt][1]=res;
	}
	printf("%lld\n",cnt+1);
	for(int i=1;i<=cnt;i++) printf("%lld %lld\n",ans[i][0],ans[i][1]);
	printf("%lld %lld\n",n,n-1);
};
signed main(){
	File(factorial);
	for(int Ts=read();Ts;Ts--) Work();
	exit(0);	
}

B. 子集

签到题.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define int long long
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[]()->int{
		int w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:(-w);
	};
} using namespace BSS;

const int N=1e6+21;

int n,m,sum;
vector<int> vec[N];
auto SpWork1=[]()->void{
	int x=n/m-2,j=1;
	for(int i=1;i<=x;i++){
		if(i&1) for(int k=1;k<=m;k++) vec[k].pb(j++);
		else for(int k=m;k;k--) vec[k].pb(j++);
	}
	for(int i=m/2+1;i<=m;i++) vec[i].pb(j++);
	for(int i=1,lmi=m/2;i<=lmi;i++) vec[i].pb(j++);
	for(int i=m/2+1,k=n;i<=m;i++,k-=2) vec[i].pb(k);
	for(int i=1,k=n-1,lmi=m/2;i<=lmi;i++) vec[i].pb(k),k-=2;
};
auto SpWork2=[]()->void{
	for(int i=1,j=1;i<=n/m;i++){
		if(i&1) for(int k=1;k<=m;k++) vec[k].pb(j++);
		else for(int k=m;k;k--) vec[k].pb(j++);
	}
};
auto Work=[]()->void{
	n=read(),m=read(),sum=n*(n-1)>>1ll;
	if(m==1 and n==1) { puts("Yes\n1"); return ;}
	if(sum%m or n==m) { puts("No"); return ; }
	// assert(((n&1)==0 and ((n/m)&1))==0);
	((n/m)&1) ? SpWork1() : SpWork2();
	puts("Yes");
	for(int i=1;i<=m;i++){
		for(auto j : vec[i]) printf("%lld ",j);
		puts("");
	}
	for(int i=1;i<=m;i++) vec[i].clear();
};
signed main(){
	File(subset);
	for(int Ts=read();Ts;Ts--) Work();
	exit(0);
}

C. 混凝土粉末

分块没打出来,自己还是没掌握得更好.

正解树状数组二分 \(+\) 扫描线.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define int long long
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[]()->int{
		int w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:(-w);
	};
} using namespace BSS;

#define fi first
#define se second
const int N=1e6+21;

int m,n,ops;
int ans[N];
struct I { int opt,x,y,h; } p[N];
vector<pair<int,int> > inc[N],dic[N],qry[N];
struct FenWick{
	int res=0; int c[N];
	inline void update(int x,int w){
		for(;x<=ops;x+=lbt(x)) c[x]+=w;
	}
	inline int query(int lmx,int y,int x=0){
		for(int i=20;~i;i--){
			if((x|1<<i)<=lmx and c[x|1<<i]<y) x|=1<<i,y-=c[x];
		}
		return x==lmx ? 0 : x+1 ;
	}
}bit;
signed main(){
	File(concrete);
	n=read(),ops=read();
	for(int i=1;i<=ops;i++){
		if((p[i].opt=read())&1){
			p[i].x=read(),p[i].y=read(),p[i].h=read();
			inc[p[i].x].pb(mp(p[i].h,i)),dic[p[i].y].pb(mp(p[i].h,i));
		}
		else{
			p[i].x=read(),p[i].y=read();
			qry[p[i].x].pb(mp(p[i].y,i));
		}
	}
	for(int i=1;i<=n;i++){
		for(auto j : inc[i]) bit.update(j.se,j.fi);
		for(auto j : qry[i]) ans[j.se]=bit.query(j.se,j.fi);
		for(auto j : dic[i]) bit.update(j.se,-j.fi);
	}
	for(int i=1;i<=ops;i++) if(p[i].opt&2) printf("%lld\n",ans[i]);
	exit(0);
}

D. 排水系统

\(DAG\) 上跑 \(dp\),一看是期望,果断选择线性拆开求和.

然后考虑每条边删去后的贡献,暴力的思想就是删掉之后分别统计.

考虑不再枚举重复状态,也就是充分利用已有状态,不难想到要在最原始的图上做一些措施.

首先思考如果每条边的 \(a\) 都是 \(0\),那么很容易就做出来;

如果只有一条边的 \(a\) 不是 \(0\),那么不难想到就是要删掉之后分给其它点,也很容易;

现在考虑如果有两条边的 \(a\) 不是 \(0\),那么考虑在做第二条边的时候怎么做才能使用到做第一条边的图.

发现如果根据提题意硬做,那么很难利用做之前的边的时候出现的图,所以可以考虑转化,将贡献转移.

观察到一条边 \(\{u,v\}\) 删掉对于 \(u\) 的点权没有影响,但是对 \(v\)\(v\) 的兄弟有影响,所以可以选择把边删掉的影响转移到 \(u\)\(v\) 上.

于是跑两次 \(dp\) 就完了.

D_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define int long long
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[]()->int{
		int w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:(-w);
	};
} using namespace BSS;

const int mod=998244353,N=2e5+21,M=5e5+21;

int m,n,s,t,ts,sum,inv;
int d[N],cu[N],ru[N],ot[N],pt[N],val[N],inc[N],head[N];
struct I { int u,v,w,nxt; } e[M];
queue<int> que;
auto add=[](int u,int v,int w)->void{
	e[++ts].u=u,e[ts].v=v,e[ts].w=w;
	e[ts].nxt=head[u],head[u]=ts;
};
auto ksm=[](int a,int b,int c,int w=1)->int{
	for(a%=c;b;b>>=1,a=a*a%c) if(b&1) w=w*a%c;
	return w%c;
};
auto bfs=[]()->void{
	assert(que.empty());
	for(int i=1;i<=n;i++){
		val[i]=inc[i]+pt[i],d[i]=ru[i];
		if(pt[i]) que.push(i);
	}
	int u,v;
	while(que.size()){
		u=que.front(),que.pop();
		for(int i=head[u];i;i=e[i].nxt){
			(val[v=e[i].v]+=val[u]*ksm(cu[u],mod-2,mod)%mod)%=mod;
			if(!(--d[v])) que.push(v);
		}
	}
};
signed main(){
	File(water);
	n=read(),s=read(),t=read(),m=read(); int u,v,w;
	for(int i=1;i<=m;i++){
		u=read(),v=read(),w=read(),sum+=w;
		cu[u]++,ru[v]++,add(u,v,w);
	}
	for(int i=1;i<=n;i++) ot[i]=(!cu[i]),pt[i]=(!ru[i]);
	inv=ksm(sum,mod-2,mod); bfs();
	for(int i=1;i<=m;i++){
		u=e[i].u,v=e[i].v,w=e[i].w*inv%mod*val[u]%mod*ksm(cu[u]-1,mod-2,mod)%mod;
		inc[u]=(inc[u]+w)%mod,inc[v]=(inc[v]-w+mod)%mod;
	}
	bfs();
	for(int i=1;i<=n;i++) if(ot[i]) printf("%lld ",val[i]);
	exit(0);
}
posted @ 2021-11-04 16:53  AaMuXiiiiii  阅读(101)  评论(1编辑  收藏  举报