9.7多校联考

四个质数的和


【题目描述】
给定了一个正整数 N。有多少种方法将 N 分解成为四个质数 a,b,c,d 的和。
例如:9 = 2 + 2 + 2 + 3 = 2 + 2 + 3 + 2 = 2 + 3 + 2 + 2 = 3 + 2 + 2 + 2,故共有 4 种方法将 9 分
解成为四个整数。
【输入格式】
本题多组数据测试:
第一行读入一个整数 T 表示数据组数。
接下来共 T 行,每行包含一个正整数 N。
【输出格式】
共 T 行,每行一个整数表示答案。
【输入样例】
2
9
10
NOIP2019 多校联测-提高组
【输出样例】
4
6
【数据范围】
对于 10%的数据,N≤10。
对于 40%的数据,N≤100。
对于 70%的数据,N≤1000。
对于 100%的数据,T≤10,N≤100000。

代码

#include
#include
#define N 100010
#define ll long long
int t,n,k;
int vis[N];
int p[N];
ll ans;
int main()
{
	freopen("plus.in","r",stdin);
	freopen("plus.out","w",stdout);
	p[1]=2;
	int cnt=1,nn=N-10;
	for(int i=3;i<=nn;i+=2)
		if(!vis[i])
		{
			p[++cnt]=i;
			for(int j=i+i;j<=N;j+=i)vis[j]=1;
		}
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=cnt;i++)
		for(int j=1;j<=cnt&&p[j]+p[i]<=nn;j++)
			vis[p[i]+p[j]]++;
	scanf("%d",&t);
	while(t--)
	{
		ans=0;
		scanf("%d",&n);
		for(int i=4;i<=n-4;i++)
			ans+=1ll*vis[i]*vis[n-i];
		printf("%lld\n",ans);
	}
}

匹配最大异或


【题目描述】
假设给定了两个整数 m,n。有 n 个互不相同的整数 x 1 ,x 2 ,...,x n (0≤x i ≤2 m -1)。对于每
一个属于 0 到 2 m -1 的 y,我们找到 p y 使得 x p_y 异或 y 有最大值。即对于任意的 i≠p y ,
有 y⊕x p_y >y⊕ x i 。(其中⊕表示二进制异或)。
现在我们把这个问题反过来。给定 m 和 n,以及序列 p 0 ,p 1 ,...,p 2^m-1 ,计算有多少个
不同序列 x 1 ,x 2 ,...,x n 可以通过上文描述的问题生成出序列 p。两个序列是不同的当且仅当
存在一个 i 使得两个序列中 x i 是不同的。
答案对 1000000007(10 9 +7)取模。
【输入格式】
第一行两个用空格隔开的整数 m,n。其中 2 m 是 p 序列的长度,n 是 x 序列的长度。
之后 2 m 行,每行一个整数,表示 p 序列。保证 1 到 n 中的每一个数在输入中都至
少出现一次。
【输出格式】
输出一行一个整数表示答案。
【输入输出样例】
样例输入 1:
3 6
1
1
2
2
3
4
5
6
样例输出 1:
4
样例输入 2:
NOIP2019 多校联测-提高组
2 3
1
2
1
3
样例输出 2:
0
样例输入 3:
3 8
1
2
3
4
5
6
7
8
样例输出 3:
1
【数据范围】
对于 30%的数据:m≤3,n≤4
另外 10%的数据:m=0
另外 10%的数据:n=1
另外 10%的数据:p i =i
对于 100%的数据:0≤m≤16,1≤n≤2 m

代码

#include
#define mod 1000000007
#define ll long long
int m,n;
int a;
int p[(1<<16)];
ll dfs(int l,int r)
{
	if(l==r)return 1ll;
	int mid=(l+r)>>1;
	bool f=1;
	for(int i=l,j=mid+1;i<=mid;i++,j++)
		if(p[i]!=p[j])
		{
			f=0;
			break;
		}
	if(f)return dfs(l,mid)*2ll%mod;
	//当 [l,mid]段和[mid+1,r]完全相同时,该位为0或1均可 
	for(int i=l,j=mid+1;i<=mid;i++,j++)
		if(p[i]==p[j])return 0;
	//当[l,mid]段和[mid+1,r]不完全相同时,该位不同但这两段有相同指向的Xi,矛盾无解 
	return dfs(l,mid)*dfs(mid+1,r)%mod;
}
int main()
{
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	scanf("%d%d",&m,&n);
	for(int i=0;i<(1<

染色相邻的边


【题目描述】
给定一个 N 个点的树,点的标号从 1 到 N。
一条树上点 a 到点 b 的简单路径 P 是一个 k 个点的序列(a=P1,P2,...,Pk=b),相邻的
两个点之间有边连接且任何一个点至多在序列中出现一次。注意 a 可能和 b 是相等的。
简单路径上的边就是连接序列上相邻两个点的边。
一条简单路径的邻边是只有一个端点在简单路径上的边。
树上的每条边是黑色的或者白色的。最开始所有的边都是黑色的。有 Q 次操作,
有两种操作类型。
0. 计算 a 到 b 的简单路径上有多少条边是黑色的。
1. 将简单路径 a 到 b 上的边全部设置成白色的。将简单路径 a 到 b 上的邻边设置成
黑色的。
【输入格式】
第一行一个整数 N(1≤N≤200000)。
NOIP2019 多校联测-提高组
接下来 N-1 行,每行两个整数 a i ,b i ,表示一条树边。保证读入的是一棵树。
接下来一行一个整数 Q(1≤Q≤300000)。
接下来 Q 行,每行三个整数 t i , a i , b i 。其中 t i 表示操作类型。
【输出格式】
对于每个 0 操作,输出一行一个整数表示答案。
【样例输入 1】
8
1 7
7 8
1 5
1 3
5 2
5 6
6 4
5
1 2 7
0 2 8
1 6 7
0 1 2
0 3 8
【样例输出 1】
1
1
2
【样例 1 图】
NOIP2019 多校联测-提高组
【样例输入 2】
19
1 2
2 3
1 5
5 4
5 6
6 7
6 8
1 11
11 12
11 13
11 10
10 9
13 14
13 15
15 16
15 17
15 18
15 19
6
1 19 8
0 16 2
0 16 3
1 12 9
0 19 8
0 16 9
【样例输出 2】
2
3
2
2
【数据范围】
对于 5%的数据:N=1
对于 20%的数据:N≤200
对于 30%的数据:N≤2000
另外 20%的数据:树的形态是一条链
另外 30%的数据:操作 1 中 a i =b i ,且 a i 是随机生成的。
对于 100%的数据:1≤N≤200000,1≤Q≤300000

附上50分的代码
 

#include
#include
#include
#include
using namespace std;
#define N 2002
int n,q,a,b,t;
vectorg[N];
int fa[N],f[N][25];//?f?25
int dep[N];
int mp[N][N],col[N];
void dfs(int u,int fath)
{
	f[u][0]=fa[u]=fath;
	for(int i=0;idep[a])swap(a,b);
				while(dep[a]!=dep[b])
				{
					turn(fa[a]);col[mp[a][fa[a]]]=0;a=fa[a];
				}
				while(fa[a]!=fa[b])
				{
					turn(fa[a]);col[mp[a][fa[a]]]=0;a=fa[a];
					turn(fa[b]);col[mp[b][fa[b]]]=0;b=fa[b];
				}
				if(a!=b)
				{
					turn(fa[a]);
					col[mp[a][fa[a]]]=0;
					col[mp[b][fa[b]]]=0;
				} 
			}
			else
			{
				int res=0;
				if(dep[b]>dep[a])swap(a,b);
				while(dep[a]!=dep[b])
				{
					if(col[mp[a][fa[a]]])res++;
					a=fa[a];
				}
				while(a!=b)
				{
					if(col[mp[a][fa[a]]])res++;a=fa[a];
					if(col[mp[b][fa[b]]])res++;b=fa[b];
				}
				printf("%d\n",res);
			}
		}
	}
	
}

 

你可能感兴趣的:(联考)