【GDKOI】2021提高Day3

【GDKOI】2021提高Day3

2021 年广东省重点中学信息学冬令营 (GDKOI 2021)
提高组 第三试
2021 年 1 月 31 日
注意事项

  1. 严格按照题目所要求的格式进行输入、输出,否则严重影响得分。
  2. 题目测试数据有严格的时间限制,超时不得分。
  3. 输入文件格式不用判错;输入输出文件名均已给定,不用键盘输入。
  4. 提交文件夹及保存方式请参考《考生注意事项》。评测以源程序为准。
  5. 评测环境为 NOI 系列活动标准竞赛环境,编译器版本为 g++ 4.8.4。
  6. 对于 C++ 选手,64 位整数输入输出格式为 %lld。
  7. 本次竞赛的最终解释权归 GDOI 评委会所有。
    试题名称 懒惰的出题人 空中恋爱论 生命游戏 聚类
    提交文件名 lazy.cpp love.cpp lifegame.cpp clusters.cpp
    输入文件名 lazy.in love.in lifegame.in clusters.in
    输出文件名 lazy.out love.out lifegame.out clusters.out
    时间限制 2s 3s 6s 1s
    空间限制 512MB 512MB 512MB 512MB
    编译选项 -O2
    满分 100 100 100 100
    第 1 页 共 7 页
    GDKOI 2021 TG Day3

第一题 懒惰的出题人

提交文件: lazy.cpp
输入文件: lazy.in
输出文件: lazy.out
时间空间限制: 2s, 512MB
出题人很懒,不想写很长的题面,也不想看很长的题面。
出题人很善良,不想让选手们看很长的题面。
于是这题题面十分简短:
给定一棵 n 个节点的树。编号为 i 的节点权值为 ai。树上的路径对可表示为 (x, y, u, v),其中 x ≤ y, u ≤ v,
表示 x 到 y 和 u 到 v 的一对路径。
定义一个路径对的价值 f(x, y, u, v) 为同时在两条路径上的所有点的点权的最小公倍数(lcm),求所有
可能的路径对的价值乘积,即
∏ 1≤x≤y≤n,1≤u≤v≤n f(x, y, u, v)
由于结果可能很大,所以你只需要输出答案对 109 + 7 取模。
输入格式
第一行一个整数 n,表示树的大小。
第二行 n 个整数,第 i 个数表示第 i 个点的价值 ai。
接下来 nn 1 行,每行两个整数 ui
, vi,表示树上的一条边。
输出格式
输出一行一个整数,表示答案对 109 + 7 取模。
样例数据
lazy.in lazy.out
4
2 2 1 4
1 2
2 3
2 4
248320570
数据范围
对于 20% 的数据,n ≤ 100, ai ≤ 11;
对于 30% 的数据,n ≤ 2000, ai ≤ 11;
对于 50% 的数据,n ≤ 2 × 104;
对于 60% 的数据,n ≤ 8 × 104
, ai ≤ 104;
对于 80% 的数据,n ≤ 2 × 105
, ai ≤ 5 × 105;
对于 100% 的数据,n ≤ 5 × 105
, ai ≤ 5 × 106。 第 2 页 共 7 页
GDKOI 2021 TG Day3

第二题 空中恋爱论

提交文件: love.cpp
输入文件: love.in
输出文件: love.out
时间空间限制: 3s, 512MB
感情在空中高速飞行,就会化成风,我们互相追逐……
南南 n 天前幸福脱单,这 n 天每天她都有一个恋爱收获 ai (|ai
| ≤ 1) 和恋爱体验 bi。当然,恋爱中可能
出现吵架,恋爱也可能导致降智,因此 ai 和 bi 都有可能是负数。
南南是很有思想的女孩,她可以选定这 n 天中的一段连续的日子,得到一段正向回忆和反向思考。具体
地,如果她选择了 l, r 满足 1 ≤ l ≤ r ≤ n,那么这可以构成一个收获值为 ∑ri=l ai、体验值为 ∑ri=l bi 的正向
回忆,也可以构成一个收获值为 | ∑ri=l ai、体验值为 | ∑ri=l bi 的反向思考。
我们把正向回忆和反向思考统称为回忆,显然南南总共有 n(n + 1) 个回忆,这些回忆的收获值都在落在
区间 [∪ n, n] 中。
只有体验值大于 0 的回忆才是好的回忆。现在南南想要知道对于每一个 i ∈ [∪ n, n],有多少好的回忆的
收获值是 i。
输入格式
第一行一个正整数 n。
第二行 n 个整数,表示 a1, · · · , an。
第三行 n 个整数,表示 b1, · · · , bn。
输出格式
一行 2n + 1 个整数,分别表示收获值为 | n, · · · , n 的好的回忆的数量。
样例数据
love.in love.out
3
1 1 1
1 -2 3
0 1 1 0 2 1 1
5
1 1 -1 -1 1
1 -2 3 -4 5
0 0 0 1 3 4 6 1 0 0 0
数据范围
对于 20% 的数据,1 ≤ n ≤ 1000;
对于 60% 的数据,1 ≤ n ≤ 50000;
对于 100% 的数据,1 ≤ n ≤ 105, |ai
| ≤ 1, |bi
| ≤ 109 第 3 页 共 7 页
GDKOI 2021 TG Day3

第三题 生命游戏

提交文件: lifegame.cpp
输入文件: lifegame.in
输出文件: lifegame.out
时间空间限制: 6s, 512MB
生命游戏是一个零玩家游戏——它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或
死了的细胞,而一个细胞在下一个时刻生死取决于相邻四个方格中活着的或死了的细胞的数量。
——维基百科
今天我们将要研究异或生命游戏,具体而言,对于任意一个细胞,当且仅当该细胞相邻四个方格中存活
细胞的数量为奇数个时,该细胞在下一时刻存活。
现在某个异或生命游戏初始(时刻 0)只有 n 个存活的细胞,你能算出从时刻 L 到时刻 R 的存活细胞
的数量之和吗?
输入格式
第一行包含四个整数 n, L, R, type。其中 n, L, R 的含义如题面所示,type 是数据类型提示,它可以帮你
获取部分分,这个参数的含义在【数据范围】中有具体的描述。
接下来 n 行,每行两个整数 xi
, yi,表示第 i 个存活细胞的坐标。
输出格式
输出一个整数,表示从时刻 L 到时刻 R 的存活细胞的数量之和。答案对 998244353 取模。
样例数据
lifegame.in lifegame.out
3 0 3 2
0 -1
0 0
2 2
55
2 0 89 2
-15 -44
47 -34
37830
8 19260817 20210131 2
9 1
-1 -9
0 10
0 4
5 -3
-7 1
1 5
4 2
767830283
样例解释
对于样例 1,演化的 4 个时刻的细胞状态分别为
第 4 页 共 7 页
GDKOI 2021 TG Day3
数据范围
data id n = R ≤ type
1 1
100
0 2 2000
3
109 1
4-5 2 6 2 0 7 1
8-9 2000
2
10 105
11
10
100
12-13 2000
14 109
15 2000
16 10 1 5
17-18
15
109
19 100
2
20 109
数据类型 type 的含义为:
• type = 0,保证对于所有初始状态为活着的细胞,均有 x + y 的奇偶性互不相同。
• type = 1,保证 L = R,即只询问第 L® 个时刻时存活细胞的数量。
• type = 2,数据无特殊限制。
第 5 页 共 7 页
GDKOI 2021 TG Day3

第四题 聚类

提交文件: clusters.cpp
输入文件: clusters.in
输出文件: clusters.out
时间空间限制: 1s, 512MB
有一个度量图 G = (V, E),满足如下性质:
• G 是带权完全无向图;
• 对于任意三个不同的点 x, y, z ∈ V ,边权满足三角形不等式,即 d(x, z) ≤ d(x, y) + d(y, z)
给定一个值 k,现在要将节点分成 m 个集合 S1, S2, · · · , Sm,满足:
• ∀i = j, Si ∩ Sj = ∅ • S1 ∪ S2 ∪ · · · ∪ Sm = V • ∀i, |Si
| ≥ k,即每个集合要包含至少 k 个节点
对每个集合 Si 选择一个中心节点 ci ∈ Si,定义 Si 的半径 ri 为 Si 中的点与 ci 距离的最大值,即
ri = maxx∈Si d(x, ci)
要求最小化 ri 的最大值。任意输出一种能使 ri 最大值最小的方案。(注意:不同子任务的评分方式不同)
输入格式
第一行三个整数 n, k, sub,表示 G 的节点数,每个集合的大小的下界以及子任务编号。
接下来 n 行,每行 n 个整数,其中第 i 行第 j 个整数表示节点 i 和 j 之间两边的边权 d(i, j)。
输出格式
第一行一个整数 m,表示集合的数量。
接下来 m 行,其中第 i 行第一个数字为 |Si|,接下来 |Si| 个数字表示 Si 中的节点编号。
最后一行 m 个数字,其中第 i 个为 ci,即 Si 选择的中心节点
样例数据
clusters.in clusters.out
3 1 1
0 3 3
3 0 5
3 5 0
3
1 1
1 2
1 3
1 2 3
4 2 2
0 1 2 3
1 0 1 2
2 1 0 1
3 2 1 0
2
2 1 2
2 3 4
1 3
第 6 页 共 7 页
GDKOI 2021 TG Day3
数据范围
对于所有数据,n ≤ 200, 0 ≤ d(i, j) ≤ 106。
Subtask1(20pts):n ≤ 15
Subtask2(20pts):G 的生成方式如下:

  1. 生成 n 个整数 a1, a2, · · · , an
  2. 令 V = {1, 2, · · · , n},令 i 与 j 之间连边的边权为 |ai 惖 aj |
    Subtask3(20pts):k > n3
    Subtask4(40pts):记 R 为选手输出方案的半径,令 R∗ 为答案半径,那么选手得分为 S · e
    min{0,2∈ RR∗ },其
    中 S 为数据点得分,子任务得分为所有数据得分的最小值,注意只需要 RR∗ ≤ 2 就可以得到满分。
    第 7 页 共 7 页

代码

全部错误

T1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long a[500010],head[500010],tot=0,ans=1,n;
bool d1[500010],d2[500010];
long long p=1000000007;
struct jgt
{
	int x,y,nxt;
}e[500010];
long long lcm(long long s1,long long s2)
{
	long long t1=s1,t2=s2,r;
	for(r=t1%t2;r;t1=t2,t2=r,r=t1%t2);
	return s1/t2*s2%p;
}
void dfs(long long q,long long dep)
{
	long long i,js;
//	cout<<q<<' '<<dep<<" dfs\n";
	if(dep>=q)
	{
		for(js=1,i=1;i<=n;i++)
			if(d1[i]&&d2[i])
				js=lcm(js,a[i]);
//		cout<<js<<endl;
		ans=ans*js%p;
	}
	for(i=head[dep];i;i=e[i].nxt)
		if(!d2[e[i].y])
		{
			d2[e[i].y]=1;
			dfs(q,e[i].y);
			d2[e[i].y]=0;
		}
	return;
}
void DFS(long long q,long long dep)
{
	long long i;
//	cout<<q<<' '<<dep<<" DFS\n";
	if(dep>=q)
	{
		for(i=1;i<=n;i++)
			d2[i]=1,dfs(i,i),d2[i]=0;
	}
	for(i=head[dep];i;i=e[i].nxt)
		if(!d1[e[i].y])
		{
			d1[e[i].y]=1;
			DFS(q,e[i].y);
			d1[e[i].y]=0;
		}
	return;
}
int main()
{
	freopen("lazy.in","r",stdin);
	freopen("lazy.out","w",stdout);
	long long i,x,y;
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	for(i=1;i<n;i++)
	{
		scanf("%lld%lld",&x,&y);
		e[++tot].x=x,e[tot].y=y,e[tot].nxt=head[x],head[x]=tot;
		e[++tot].x=y,e[tot].y=x,e[tot].nxt=head[y],head[y]=tot;
	}
	for(i=1;i<=n;i++)
		d1[i]=1,DFS(i,i),d1[i]=0;
	printf("%lld",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T2

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long a[100010],b[100010],suma[100010],sumb[100010],ansf[100010],ansz[100010];
int main()
{
	freopen("love.in","r",stdin);
	freopen("love.out","w",stdout);
	long long n,i,j,tem;
	memset(ansf,0,sizeof(ansf));
	memset(ansz,0,sizeof(ansz));
	suma[0]=sumb[0]=0;
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
		scanf("%lld",&a[i]),suma[i]=suma[i-1]+a[i];
	for(i=1;i<=n;i++)
		scanf("%lld",&b[i]),sumb[i]=sumb[i-1]+b[i];
	for(i=1;i<=n;i++)
	{
		for(j=i;j<=n;j++)
		{
			if(sumb[j]-sumb[i-1]>0)
			{
				tem=suma[j]-suma[i-1];
				if(tem<0) ansf[-tem]++;
				else ansz[tem]++;
			}
			if(sumb[i-1]-sumb[j]>0)
			{
				tem=suma[i-1]-suma[j];
				if(tem<0) ansf[-tem]++;
				else ansz[tem]++;
			}
		}
	}
	for(i=n;i>0;i--)
		printf("%lld ",ansf[i]);
	for(i=0;i<=n;i++)
		printf("%lld ",ansz[i]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T3

#include<iostream>
#include<cstdio>
#include<queue>
#include<deque>
using namespace std;
long long p=998244353;
long long dp[100010];
int main()
{
	freopen("lifegame.in","r",stdin);
	freopen("lifegame.out","w",stdout);
	long long n,L,R,type,ans,i;
	scanf("%lld%lld%lld%lld",&n,&L,&R,&type);
/*	for(i=1;i<=n;i++)
	{
		scanf("%d%d",&tem.x,&tem.y);
		a[++r]=tem;
	}*/
	dp[0]=1;
	for(i=1;i<L;i++)
		dp[i]=(dp[i-1]<<2)%p;
	for(i=L;i<=R;i++)
	{
		dp[i]=(dp[i-1]*4)%p;
		ans=(ans+dp[i])%p;
	}
	printf("%lld",ans);
/*	ans=n;
	for(i=1;i<L;i++)
	{
		for(j=l;j<=r;j++)
		{
			if(cnt&1)
				a[++r]=a[l];
			l++;
			for(k=0;k<4;k++)
			{
				dx=a[l].x+fs[k][0];
				dy=a[l].y+fs[k][1];
				cnt=1;
				for(v=l+1;v<=r;v++)
					if(dx==a[v].x&&dy==a[v].y)
						cnt=0;
				if(!cnt)
				{
					
				}
			}
		}
	}
	for(i=L;i<=R;i++)
	{
		
	}*/
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T4

#include<iostream>
#include<cstdio>
#include<queue>
#include<deque>
using namespace std;
long long d[210][210],ans[210];
int main()
{
	freopen("clusters.in","r",stdin);
	freopen("clusters.out","w",stdout);
	long long n,i,j,k,sub,l;
	scanf("%lld%lld%lld",&n,&k,&sub);
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			scanf("%lld",&d[i][j]);
		}
	}
	printf("%lld\n",n/k);
	for(i=1,j=1;i<n/k;i++)
	{
		printf("%lld",k);
		ans[i]=j;
		for(l=0;l<k;l++,j++)
			printf(" %lld",j);
		printf("\n");
	}
	printf("%lld",k+n%k);
	ans[n/k]=j;
	for(;j<=n;j++)
		printf(" %lld",j);
	printf("\n");
	for(i=1;i<=n/k;i++)
		printf("%lld ",ans[i]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值