2023.2.22模拟赛

T1
题意:
构造一个以1开头,由\(n\)个1和\(m\)个0组成的01串,使得其表示的二进制数可以被三整除,求其最大值和最小值。
思路:
分讨:
1.n为偶,m为偶,最大值\(\overset{n}{1\dots 1} \overset{m}{0\dots 0}\),最小值\(1\overset{m}{0\dots 0}\overset{n-1}{1\dots 1}\)
2.n为偶,m为奇,最大值\(\overset{n}{1\dots 1} \overset{m}{0\dots 0}\),最小值\(1\overset{m-1}{0\dots 0}10\overset{n-2}{1\dots 1}\)
3.n为奇,m为偶,最大值\(\overset{n-2}{1\dots 1}0101\overset{m-2}{0\dots 0}\),最小值\(1\overset{m-1}{0\dots 0}10\overset{n-2}{1\dots 1}\)
4.n为奇,m为奇,最大值\(\overset{n-2}{1\dots 1}0101\overset{m-2}{0\dots 0}\),最小值\(1\overset{m-2}{0\dots 0}1010\overset{n-3}{1\dots 1}\)
代码:

#include<iostream>
#include<cstdio>
using namespace std;
int kd(){
	int x=0,f=1;
	char a=getchar();
	while(a<'0'||a>'9'){
		if(a=='-'){
			f=-1;
		}
		a=getchar();
	}
	while(a>='0'&&a<='9'){
		x=x*10+a-'0';
		a=getchar(); 
	}
	return x*f;
}
int t;
int n,m;
int main(){
	t=kd();
	while(t--){
		n=kd();m=kd();
		if(n<=1){
			printf("-1");
		}
		else{
			if(n%2==0){
				for(int i=1;i<=n;i++){
					printf("1");
				}
				for(int i=1;i<=m;i++){
					printf("0");
				}
			}
			else{
				if(m<=1){
					printf("-1");
				}
				else{
					for(int i=1;i<=n-2;i++){
						printf("1");
					}
					printf("0101");
					for(int i=1;i<=m-2;i++){
						printf("0");
					}
				}
			}
		}
		printf("\n");
		if(n<=1){
			printf("-1");
		}
		else{
			if(n%2==0){
				printf("1");
				if((n+m)%2==0){
					for(int i=1;i<=m;i++){
						printf("0");
					}
					for(int i=1;i<=n-1;i++){
						printf("1");
					}
				}
				else{
					for(int i=1;i<=m-1;i++){
						printf("0");
					}
					printf("10");
					for(int i=1;i<=n-2;i++){
						printf("1");
					}
				}
			}
			else{
				if((n+m)%2==1){
					if(m==0){
						printf("-1");
					}
					else{
						printf("1");
						for(int i=1;i<=m-1;i++){
							printf("0");
						}
						printf("10");
						for(int i=1;i<=n-2;i++){
							printf("1");
						}
					}
				}
				else{
					if(m==1){
						printf("-1");
					}
					else{
						printf("1");
						for(int i=1;i<=m-2;i++){
							printf("0");
						}
						printf("1010");
						for(int i=1;i<=n-3;i++){
							printf("1");
						}
					}
				}
			}
		}
		printf("\n");
	}
	return 0;
}

T2
题意:
给定一个数\(n\),计数\(n\)的排列满足\(p_{i}\)的因子个数等于\(i\)的因子个数。\(t\)组询问,答案对\(500009\)取模。\(n<=1e9\)
思路:
首先考虑线性筛因子个数\(C_{i}=\prod (a_{k}+1)\)
1.\(i\)为质数。因子个数为2。
2.\(i=j\times s\) (\(s\)为质数),且 \(j\)\(s\)的倍数。因子个数为\(C_{j}\times 2\)
3.\(i=j\times s\) (\(s\)为质数),且 \(s\mid j\)\(C_{i}=\frac{C_{j}\times (a_{s}+1+1)}{a_{s}+1}=2\times C_{j}-\frac{C_{j}\times a_{s}}{a_{s}+1}=2\times C_{j}-C_{\frac{j}{s}}\),所以因子个数为\(2\times C_{j}-C_{\frac{j}{s}}\)
这样就可以统计出\(C_{i}=k\)的个数 \(B_{k}\),答案为\(\prod_{B_{k}>0} (B_{k}!)\),当\(i\ge 2229283\)时,因为模数,答案为0。
代码:

#include<iostream>
#define mod 500009
#define int long long
using namespace std;
int kd(){
	int x=0,f=1;
	char a=getchar();
	while(a<'0'||a>'9'){
		if(a=='-'){
			f=-1;
		}
		a=getchar();
	}
	while(a>='0'&&a<='9'){
		x=x*10+a-'0';
		a=getchar();
	}
	return x*f;
}
int t;
int n;
int tong[5000010];
bool prime[5000010];
int ss[5000010];
int yz[5000010];
int f[5000010];
int g[5000010];
void shai(){
	yz[1]=1;
	g[1]=1;
	for(int i=2;i<=5000000;i++){
		if(prime[i]==0){
			ss[++ss[0]]=i;
			yz[i]=2;
		}
		tong[yz[i]]++;
		f[i]=tong[yz[i]];
		g[i]=g[i-1]*f[i]%mod;
		for(int j=1;j<=ss[0]&&i*ss[j]<=5000000;j++){
			prime[i*ss[j]]=1;
			if(i%ss[j]!=0){
				yz[i*ss[j]]=yz[i]*2%mod;
			}
			else{
				yz[i*ss[j]]=((yz[i]*2-yz[i/ss[j]])%mod+mod)%mod;
				break;
			}
		}
	}
}
signed main(){
	t=kd();
	shai();
	while(t--){
		n=kd();
		if(n>5000000){
			printf("0\n");
		}
		else{
			printf("%lld\n",g[n]);
		}
	}
	return 0;
}

T3
题意:
\(n\)个点\((X,Y)\)\(q\)个直角边与x轴和y轴平行的等腰直角三角形\((x,y,d)\),求每个等腰直角三角形覆盖的点有多少个。
思路:
容斥。

$\overset{X\ge x,Y\ge y,X+Y\le x+y+d}{7} =\overset{n}{(1+2+3+4+5+6+7)} -\overset{X<x}{(1+2+3)} -\overset{Y<y}{(3+4+5)} -\overset{X+Y>x+y+d}{(5+6+1)} +\overset{X<x,X+Y>x+y+d}{1} +\overset{X<x,Y<y}{3} +\overset{Y<y,X+Y>x+y+d}{5} $
\(1,3,5\)用二维数点求。
代码:

#include<iostream>
#include<algorithm>
using namespace std;
int kd(){
	int x=0,f=1;
	char a=getchar();
	while(a<'0'||a>'9'){
		if(a=='-'){
			f=-1;
		}
		a=getchar();
	}
	while(a>='0'&&a<='9'){
		x=x*10+a-'0';
		a=getchar();
	}
	return x*f;
}
int n,q;
struct node{
	int x,y;
	int d;
	int id;
}b[1000010],a[1000010];
int ans[1000010];
bool cmp(node x,node y){
	return x.x<y.x;
}
bool cnp(node x,node y){
	return x.y<y.y;
}
bool cup(node x,node y){
	return x.d>y.d;
}
int c[3000010];
int lowbit(int x){
	return x&(-x);
}
void add(int x,int k){
	for(;x<=3000000;x+=lowbit(x)){
		c[x]+=k;
	}
}
int getsum(int x){
	int sum=0;
	for(;x;x-=lowbit(x)){
		sum+=c[x];
	}
	return sum;
}
int main(){
	n=kd();q=kd();
	for(int i=1;i<=n;i++){
		a[i].x=kd();a[i].y=kd();
		a[i].d=a[i].x+a[i].y;
	}
	for(int i=1;i<=q;i++){
		b[i].x=kd();b[i].y=kd();b[i].d=b[i].x+b[i].y+kd();
		b[i].id=i;
		ans[i]=n;
	}
	sort(a+1,a+n+1,cmp);
	sort(b+1,b+q+1,cmp);
	int i=1;
	for(int j=1;j<=q;j++){
		while(i<=n&&a[i].x<b[j].x){
			i++;
		}
		ans[b[j].id]-=i-1;
	}
	i=1;
	for(int j=1;j<=q;j++){
		while(i<=n&&a[i].x<b[j].x){
			add(a[i].y,1);
			i++;
		}
		ans[b[j].id]+=getsum(b[j].y-1);
	}
	for(i=i-1;i>=1;i--){
		add(a[i].y,-1);
	}
	i=1;
	for(int j=1;j<=q;j++){
		while(i<=n&&a[i].x<b[j].x){
			add(a[i].d,1);
			i++;
		}
		ans[b[j].id]+=i-1-getsum(b[j].d);
	}
	for(i=i-1;i>=1;i--){
		add(a[i].d,-1);
	}
	sort(a+1,a+n+1,cnp);
	sort(b+1,b+q+1,cnp);
	i=1;
	for(int j=1;j<=q;j++){
		while(i<=n&&a[i].y<b[j].y){
			i++;
		}
		ans[b[j].id]-=i-1;
	}
	i=1;
	for(int j=1;j<=q;j++){
		while(i<=n&&a[i].y<b[j].y){
			add(a[i].d,1);
			i++;
		}
		ans[b[j].id]+=i-1-getsum(b[j].d);
	}
	for(i=i-1;i>=1;i--){
		add(a[i].d,-1);
	}
	sort(a+1,a+n+1,cup);
	sort(b+1,b+q+1,cup);
	i=1;
	for(int j=1;j<=q;j++){
		while(i<=n&&a[i].d>b[j].d){
			i++;
		}
		ans[b[j].id]-=i-1;
	}
	for(int j=1;j<=q;j++){
		cout<<ans[j]<<endl;
	}
	return 0;
}

T4
题意:
计数,长度为\(n\)的字符序列\(a_{i}\in [x_{i},y_{i}]\)\(m\)组限制,\((\sum_{k=l_{j}}^{r_{j}} a_{k})\mod 2=s_{j}\)
思路:
\(qian_{i}=(\sum_{k=1}^{i} a_{k})\mod 2\)
\(l_{j}-1\)\(r_{j}\)建边,当\(qian_{l_{j}-1}\)确定时,\(qian_{r_{j}}\)也一定确定,可以对搜索进行剪枝。
当某个\(i\)与其它位置没有连边时,这不会影响到其他位置的\(qian\),这样就可以对这个位置进行DP。
\(dp_{u,0/1,0/1}\)表示第\(u\)个位置\(qian_{u}=0/1\)\(a_{u}\mod 2=0/1\)
\(ans_{u,0/1,0/1,i}\)维护最小字典序序列。
代码:

#include<iostream>
#define mod 1000000007
#define int long long
using namespace std;
int kd(){
	int x=0,f=1;
	char a=getchar();
	while(a<'0'||a>'9'){
		if(a=='-'){
			f=-1;
		}
		a=getchar();
	} 
	while(a>='0'&&a<='9'){
		x=x*10+a-'0';
		a=getchar();
	}
	return x*f;
}
int n,m;
struct node{
	int x,y;
	int w[2];
}a[50];
struct nod{
	int to;
	int nxt;
	int val;
}edge[210];
int head[50],tot;
void addedge(int u,int v,int w){
	edge[++tot].to=v;
	edge[tot].nxt=head[u];
	edge[tot].val=w;
	head[u]=tot;
}
int dui[50];
int cnt[50];
int qian[50];
int dp[50][2][2];
int ans[50][2][2][50];
int pd(int u,int i,int j,int k,int h){
	for(int w=u+1;w<=n;w++){
		if(ans[u+1][i][j][w]<ans[u][k][h][w]){
			return 1;
		}
		if(ans[u+1][i][j][w]>ans[u][k][h][w]){
			return 0;
		}
	}
	return 1;
}
void dfs(int u){
	if(u>n){
		return ;
	}
	for(int j=1;j<=n;j++){
		ans[u][0][0][j]=a[j].y;
		ans[u][0][1][j]=a[j].y;
		ans[u][1][0][j]=a[j].y;
		ans[u][1][1][j]=a[j].y;
	}
	dp[u][0][0]=0;
	dp[u][0][1]=0;
	dp[u][1][0]=0;
	dp[u][1][1]=0;
	if(cnt[u]==0){
		dfs(u+1);
		if(qian[u+1]!=1){
			dp[u][0][0]=(dp[u][0][0]+dp[u+1][0][0]*a[u].w[0]%mod)%mod;
			if(dp[u+1][0][0]>0&&pd(u,0,0,0,0)){
				for(int j=u+1;j<=n;j++){
					ans[u][0][0][j]=ans[u+1][0][0][j];
				}
				ans[u][0][0][u]=(a[u].x+1)/2*2;
			}
			dp[u][0][1]=(dp[u][0][1]+dp[u+1][0][0]*a[u].w[1]%mod)%mod;
			if(dp[u+1][0][0]>0&&pd(u,0,0,0,1)){
				for(int j=u+1;j<=n;j++){
					ans[u][0][1][j]=ans[u+1][0][0][j];
				}
				ans[u][0][1][u]=a[u].x/2*2+1;
			}
			dp[u][1][0]=(dp[u][1][0]+dp[u+1][0][1]*a[u].w[0]%mod)%mod;
			if(dp[u+1][0][1]>0&&pd(u,0,1,1,0)){
				for(int j=u+1;j<=n;j++){
					ans[u][1][0][j]=ans[u+1][0][1][j];
				}
				ans[u][1][0][u]=(a[u].x+1)/2*2;
			}
			dp[u][1][1]=(dp[u][1][1]+dp[u+1][0][1]*a[u].w[1]%mod)%mod;
			if(dp[u+1][0][1]>0&&pd(u,0,1,1,1)){
				for(int j=u+1;j<=n;j++){
					ans[u][1][1][j]=ans[u+1][0][1][j];
				}
				ans[u][1][1][u]=a[u].x/2*2+1;
			}
		}
		if(qian[u+1]!=0){
			dp[u][0][0]=(dp[u][0][0]+dp[u+1][1][1]*a[u].w[0]%mod)%mod;
			if(dp[u+1][1][1]>0&&pd(u,1,1,0,0)){
				for(int j=u+1;j<=n;j++){
					ans[u][0][0][j]=ans[u+1][1][1][j];
				}
				ans[u][0][0][u]=(a[u].x+1)/2*2;
			}
			dp[u][0][1]=(dp[u][0][1]+dp[u+1][1][1]*a[u].w[1]%mod)%mod;
			if(dp[u+1][1][1]>0&&pd(u,1,1,0,1)){
				for(int j=u+1;j<=n;j++){
					ans[u][0][1][j]=ans[u+1][1][1][j];
				}
				ans[u][0][1][u]=a[u].x/2*2+1;
			}
			dp[u][1][0]=(dp[u][1][0]+dp[u+1][1][0]*a[u].w[0]%mod)%mod;
			if(dp[u+1][1][0]>0&&pd(u,1,0,1,0)){
				for(int j=u+1;j<=n;j++){
					ans[u][1][0][j]=ans[u+1][1][0][j];
				}
				ans[u][1][0][u]=(a[u].x+1)/2*2;
			}
			dp[u][1][1]=(dp[u][1][1]+dp[u+1][1][0]*a[u].w[1]%mod)%mod;
			if(dp[u+1][1][0]>0&&pd(u,1,0,1,1)){
				for(int j=u+1;j<=n;j++){
					ans[u][1][1][j]=ans[u+1][1][0][j];
				}
				ans[u][1][1][u]=a[u].x/2*2+1;
			}
		}
		return ;
	}
	int zhan[50],top;
	int p;
	if(qian[u]!=1){
		p=0;
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(qian[v]!=-1&&qian[v]!=0^edge[i].val){
				p=1;
			}
		}
		if(p==0){
			top=0;
			int t=qian[u];
			qian[u]=0;
			for(int i=head[u];i;i=edge[i].nxt){
				int v=edge[i].to;
				if(qian[v]==-1){
					qian[v]=qian[u]^edge[i].val;
					zhan[++top]=v;
				}
			}
			dfs(u+1);
			if(qian[u+1]!=1){
				dp[u][0][0]=(dp[u][0][0]+dp[u+1][0][0]*a[u].w[0]%mod)%mod;
				if(dp[u+1][0][0]>0&&pd(u,0,0,0,0)){
					for(int j=u+1;j<=n;j++){
						ans[u][0][0][j]=ans[u+1][0][0][j];
					}
					ans[u][0][0][u]=(a[u].x+1)/2*2;
				}
				dp[u][0][1]=(dp[u][0][1]+dp[u+1][0][0]*a[u].w[1]%mod)%mod;
				if(dp[u+1][0][0]>0&&pd(u,0,0,0,1)){
					for(int j=u+1;j<=n;j++){
						ans[u][0][1][j]=ans[u+1][0][0][j];
					}
					ans[u][0][1][u]=a[u].x/2*2+1;
				}
			}
			if(qian[u+1]!=0){
				dp[u][0][0]=(dp[u][0][0]+dp[u+1][1][1]*a[u].w[0]%mod)%mod;
				if(dp[u+1][1][1]>0&&pd(u,1,1,0,0)){
					for(int j=u+1;j<=n;j++){
						ans[u][0][0][j]=ans[u+1][1][1][j];
					}
					ans[u][0][0][u]=(a[u].x+1)/2*2;
				}
				dp[u][0][1]=(dp[u][0][1]+dp[u+1][1][1]*a[u].w[1]%mod)%mod;
				if(dp[u+1][1][1]>0&&pd(u,1,1,0,1)){
					for(int j=u+1;j<=n;j++){
						ans[u][0][1][j]=ans[u+1][1][1][j];
					}
					ans[u][0][1][u]=a[u].x/2*2+1;
				}
			}
			qian[u]=t;
			for(int i=1;i<=top;i++){
				qian[zhan[i]]=-1;
			}
		}
	}
	if(qian[u]!=0){
		p=0;
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(qian[v]!=-1&&qian[v]!=1^edge[i].val){
				p=1;
			}
		}
		if(p==0){
			top=0;
			int t=qian[u];
			qian[u]=1;
			for(int i=head[u];i;i=edge[i].nxt){
				int v=edge[i].to;
				if(qian[v]==-1){
					qian[v]=qian[u]^edge[i].val;
					zhan[++top]=v;
				}
			}
			dfs(u+1);
			if(qian[u+1]!=1){
				dp[u][1][0]=(dp[u][1][0]+dp[u+1][0][1]*a[u].w[0]%mod)%mod;
				if(dp[u+1][0][1]>0&&pd(u,0,1,1,0)){
					for(int j=u+1;j<=n;j++){
						ans[u][1][0][j]=ans[u+1][0][1][j];
					}
					ans[u][1][0][u]=(a[u].x+1)/2*2;
				}
				dp[u][1][1]=(dp[u][1][1]+dp[u+1][0][1]*a[u].w[1]%mod)%mod;
				if(dp[u+1][0][1]>0&&pd(u,0,1,1,1)){
					for(int j=u+1;j<=n;j++){
						ans[u][1][1][j]=ans[u+1][0][1][j];
					}
					ans[u][1][1][u]=a[u].x/2*2+1;
				}
			}
			if(qian[u+1]!=0){
				dp[u][1][0]=(dp[u][1][0]+dp[u+1][1][0]*a[u].w[0]%mod)%mod;
				if(dp[u+1][1][0]>0&&pd(u,1,0,1,0)){
					for(int j=u+1;j<=n;j++){
						ans[u][1][0][j]=ans[u+1][1][0][j];
					}
					ans[u][1][0][u]=(a[u].x+1)/2*2;
				}
				dp[u][1][1]=(dp[u][1][1]+dp[u+1][1][0]*a[u].w[1]%mod)%mod;
				if(dp[u+1][1][0]>0&&pd(u,1,0,1,1)){
					for(int j=u+1;j<=n;j++){
						ans[u][1][1][j]=ans[u+1][1][0][j];
					}
					ans[u][1][1][u]=a[u].x/2*2+1;
				}
			}
			qian[u]=t;
			for(int i=1;i<=top;i++){
				qian[zhan[i]]=-1;
			}
		}
	}
}
signed main(){
	n=kd();m=kd();
	for(int i=1;i<=n;i++){
		a[i].x=kd();a[i].y=kd();
		qian[i]=-1;
		cnt[i]=0;
		a[i].w[1]=(a[i].y-a[i].x+1)/2;
		a[i].w[0]=(a[i].y-a[i].x+1)/2;
		if(a[i].x%2==a[i].y%2){
			if(a[i].x%2==1){
				a[i].w[1]++;
			}
			else{
				a[i].w[0]++;
			}
		}
	}
	cnt[0]=0;
	a[0].w[0]=1;
	a[0].w[1]=1;
	qian[n+1]=-1;
	for(int i=1;i<=m;i++){
		int u,v,w;
		u=kd();v=kd();w=kd();
		u--; 
		cnt[u]++;
		cnt[v]++;
		addedge(u,v,w);
	} 
	for(int i=head[0];i;i=edge[i].nxt){
		int v=edge[i].to;
		qian[v]=edge[i].val;
	}
	dp[n+1][0][0]=1;
	dp[n+1][1][0]=1;
	dfs(0); 
	cout<<dp[0][0][0]<<endl;
	if(dp[0][0][0]==0){
		cout<<-1;
	}
	else{
		for(int i=1;i<=n;i++){
			cout<<ans[0][0][0][i]<<" ";
		}
	}
	return 0;
}
posted @ 2023-02-24 13:54  zzzzzz2  阅读(50)  评论(0编辑  收藏  举报