GDUT决赛题解

决赛,我自我认为题目难度更大,反而我的心态更好了。

由于放轻松的时候反而效果更好,跟昨天的观点一样,凡是可以1A的,才算这题做得好。

A.数目不大,关键是看懂题(我自己连输入输出是什么都不清楚。。。。

然后管理员就把题下掉了。

。。批评批评啊。

。。

)bin神的代码膜拜了下。知道是状态压缩,题中说了最多6个,要么1<<6枚举,要么6!枚举。代码:

/* ***********************************************
Author        :kuangbin
Created Time  :2015/3/15 14:17:30
File Name     :GDUT\A.cpp
************************************************ */

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

const int INF = 0x3f3f3f3f;
int dp[1000];
int st[6410],cost[6410];
int num[6410];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;
	scanf("%d",&T);
	while(T--){
		int n;
		scanf("%d",&n);
		int cnt = 0;
		for(int i = 0;i < n;i++){
			int m;
			int nn;
			int p;
			scanf("%d%d",&m,&nn);
			while(m--){
				int k;
				scanf("%d",&k);
				st[cnt] = 0;
				num[cnt] = nn;
				while(k--){
					scanf("%d",&p);
					st[cnt] |= (1<<p);
				}
				scanf("%d",&cost[cnt]);
				cnt++;
			}
		}
		for(int i = 0;i < (1<<6);i++)dp[i] = INF;
		dp[0] = 0;
		for(int i = 0;i < (1<<6);i++){
			if(dp[i] == INF)continue;
			for(int j = 0;j < cnt;j++){
				if( (i&(1<<num[j])) != 0)continue;
				if( (i|st[j]) != i )continue;
				dp[i|(1<<num[j])] = min(dp[i|(1<<num[j])],dp[i]+cost[j]);
			}
		}
		int tot = (1<<6)-1;
		if(dp[tot] == INF)dp[tot] = -1;
		printf("%d\n",dp[tot]);
	}
    return 0;
}

B.区间DP,因为是随意地方插入0或者1,那么单位长度显然ans为0。两个长度作为初始化推断。然后区间DP

代码:

/* ***********************************************
Author        :kuangbin
Created Time  :2015/3/15 13:05:55
File Name     :GDUT\B.cpp
************************************************ */

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
char str[1010];
int a[1010];

int dp[1010][1010];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;
	int n;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		scanf("%s",str);
		for(int i = 0;i < n;i++)
			a[i] = str[i]-'0';
		memset(dp,0,sizeof(dp));
		for(int i = 0;i < n;i++)
			dp[i][i] = 1;
		for(int i = n-1;i >= 0;i--)
			for(int j = i+1;j < n;j++){
				dp[i][j] = j-i+1;
				if(a[i] != a[j])
					dp[i][j] = min(dp[i][j],dp[i+1][j-1]);
				dp[i][j] = min(dp[i][j],dp[i+1][j]+1);
				dp[i][j] = min(dp[i][j],dp[i][j-1]+1);
			}
		printf("%d\n",dp[0][n-1]);
	}
    return 0;
}

另外,另一种非常好的思路。依照题意来,取反,翻转。那么反复的不须要加入0或者1。转换为最多反复多少个,所以转换为LCS(Longest Common Sequence)代码不须要写吧,O(n^2)的算法。n=1000妥妥的

C.这道题表述上事实上是没有问题的,可是大家会陷于自己生活中的误区,菜怎么可能炒到一半就换种菜?这个题的第一组数据是个非常经典的小学竞赛问题:2个锅,要做出来3个饼,每一个饼须要2分钟做好,问你最少几分钟能够做好?答案是3.过程是这样:第一分钟,做第1和2个饼;第二分钟,做第2和3个饼。第三分钟,做1和3个饼。

那么,非常明显:利用的贪心思想。

把全部的饼尽可能的分到不同的锅里去。

那么就是取平均值的上整数值。可是一个菜不能分成多份,那么就是要统计出最大值,于是,求得就是平均值的上整数值和最大值的较大值。绕口,可是代码非常好懂

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <queue>
#include <stack>
using namespace std;

#define input freopen("input.txt","r",stdin)
#define output freopen("output.txt","w",stdout)
#define For1(i,a,b) for (i=a;i<b;i++)
#define For2(i,a,b) for (i=a;i<=b;i++)
#define Fill(x,a) memset(x,a,sizeof(x))
#define inf 99999999
#define pi 3.1415926535897932384626433832795028841971

int main(){
	int t,n,m;
	int Max,aver,num;
	scanf("%d",&t);
	while(t--){
		aver=Max=0;
		scanf("%d%d",&n,&m);
		while(n--){
			scanf("%d",&num);
			Max=max(Max,num);
			aver+=num;
		}
		aver=(aver+m-1)/m;
		printf("%d\n",max(aver,Max));
	}
	return 0;
}

D.数学题。

假设GCD(a,b)==n   LCM(a,b)==m   那么 m/n  是a b 的互质因子乘积    那就是枚举  1到m/n 互质的对数吧。sqrt(n)的复杂度。明显能够接受

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<set>
#include<iostream>
using namespace std;
typedef long long LL;

LL n, m;
LL Gcd(LL x, LL y)
{
	if (!y) return x;
	else
		return Gcd(y, x%y);
}
LL solve(LL n)
{
	LL sum = 0;
	LL i, j;
	for (i = 1; i <= (double)sqrt(n*1.0); i++)
	{
		if (n%i==0)
		{
			j = n / i;
			if (Gcd(i, j) == 1) ++sum;
		}
	}
	return sum;
}
int main()
{
	int T, i, Case = 0, j, k;
	//freopen("data.txt", "r", stdin);
	scanf("%d", &T);
	while (T--)
	{
		scanf("%lld%lld", &n, &m);
		if (m%n)
		{
			printf("0\n"); continue;
		}
		LL temp = m / n;
		printf("%lld\n", solve(temp));
	}
	return 0;
}

第五题。并查集基础。我当时煞笔WA了五次。。。

原因就是太过于自信。我的找爸爸直接用的fa[i]而不是getf[i]。

。。。。哭死。

。。

有些细节问题,不要一直提交的啊。。能够先做做别的题冷静冷静,或者自己写几个測试数据,检測下。20分钟罚时非常多的啊

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <queue>
#include <stack>
using namespace std;

#define input freopen("input.txt","r",stdin)
#define output freopen("output.txt","w",stdout)
#define For1(i,a,b) for (i=a;i<b;i++)
#define For2(i,a,b) for (i=a;i<=b;i++)
#define Fill(x,a) memset(x,a,sizeof(x))
#define inf 99999999
#define pi 3.1415926535897932384626433832795028841971

const long long maxn=1000050;
int t;
long long n,m;

long long fa[maxn];

void init(){
	for(long long i=0;i<=n;i++) fa[i]=i;
}

long long getf(long long x){
	if (fa[x]==x) return x;
	return fa[x]=getf(fa[x]);
}

int main(){
	input;
	long long i,j,k;
	scanf("%d",&t);
	while(t--){
		scanf("%lld%lld",&n,&m);
		init();
		while(m--){
			scanf("%lld",&i);
			scanf("%lld",&j);
			long long fi=getf(i);
			long long fj=getf(j);
			if (fi!=fj) fa[fi]=fj;
		}
		k=0;
		long long f1=getf(1);
		for(i=2;i<=n;i++){
			int fi=getf(i);
			if (fi!=f1){
				fa[fi]=f1;
				k++;
			}
		}
		printf("%lld\n",k);
	}
	return 0;
}

F.模拟。这道题没难度的哈。

依照题目的意思来呗。

要你干啥就干啥。推断n和m仅仅有100怎么循环都只是分的

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <queue>
#include <stack>
using namespace std;

#define input freopen("input.txt","r",stdin)
#define output freopen("output.txt","w",stdout)
#define For1(i,a,b) for (i=a;i<b;i++)
#define For2(i,a,b) for (i=a;i<=b;i++)
#define Fill(x,a) memset(x,a,sizeof(x))
#define inf 99999999
#define pi 3.1415926535897932384626433832795028841971

int vis[200];
int num[200];
int main(){
	//input;
	int t;
	int n,m;
	int i,j,k;
	scanf("%d",&t);
	while(t--){
		memset(vis,0,sizeof(vis));
		scanf("%d%d",&n,&m);
		for(i=1;i<=m;i++) scanf("%d",&num[i]);

		for(i=1;i<=m;i++)
			for(j=1;j<=n;j++){
				if (vis[j]) continue;
				if (j>=num[i]) vis[j]=num[i];
			}

		for(i=1;i<=n;i++) printf("%d%c",vis[i],i==n?'\n':' ');
	}
	return 0;
}

关键的细节问题是:每一个灯最多被关一次。意味着假设曾经訪问过这个点,那么之后不管大小关系,都不会理它了

G.数学题。意思是说求(1+n)*n/2这个数列之中。告诉你n,有多少个数被3整除。

看到那么大的n心里就不要慌啊,肯定是有规律的啊。肯定是不能打表的啊,肯定是小数据猜过程猜结论的啊

或者写出这个数列:1 3 6 10 15 21 28 36 45 55 66 78……

看到规律了吗?每三个数一组,每组的第一个不是3的倍数,第二个和第三个是3的倍数。程序大家自己写吧

H.DP。我最高兴的是这道题我的思路跟bin神是一样的啊,说明有些题是能够做的啊,不要自己吓自己的,比方BC33的第3题。我看着是状态压缩。。赛后理解就是个复杂一点的背包。。(扯远了。。)

定义:dp[i][j][k]代表第一个手指在i处。第二个手指在j处,当前已经完毕k格走过的最短距离。0<=i<=4,0<=j<=4,1<=k<=n。

依据题中数据,n最大10000。

放心的一次循环解决。

初始值为-1意味着当前情况取不到(非经常见的思路啊,用-1标记不可达,用正数标记最短路),初始情况呢,dp[0][0][0]=0

递推的思路也非常easy:假设新节点没去过(值为-1),去呗。去过的话,取小值呗

代码例如以下:

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <queue>
#include <stack>
using namespace std;

#define input freopen("input.txt","r",stdin)
#define output freopen("output.txt","w",stdout)
#define For1(i,a,b) for (i=a;i<b;i++)
#define For2(i,a,b) for (i=a;i<=b;i++)
#define Fill(x,a) memset(x,a,sizeof(x))
#define inf 99999999
#define pi 3.1415926535897932384626433832795028841971

int dp[10][10][10050];
int t,n;
int num[10050];

int main(){
	int i,j,k,dis;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=1;i<=n;i++) scanf("%d",&num[i]);
		memset(dp,-1,sizeof(dp));
		dp[0][0][0]=0;
		for(k=1;k<=n;k++)
			for(i=0;i<=4;i++)
				for(j=0;j<=4;j++){
					if (dp[i][j][k-1]==-1) continue;
					dis=abs(i-num[k]);
					if (dp[num[k]][j][k]==-1) dp[num[k]][j][k]=dp[i][j][k-1]+dis;
					else dp[num[k]][j][k]=min(dp[num[k]][j][k],dp[i][j][k-1]+dis);
					dis=abs(j-num[k]);
					if (dp[i][num[k]][k]==-1) dp[i][num[k]][k]=dp[i][j][k-1]+dis;
					else dp[i][num[k]][k]=min(dp[i][num[k]][k],dp[i][j][k-1]+dis);
				}
		int ans=100000000;
		for(i=0;i<=4;i++)
			for(j=0;j<=4;j++)
				if (dp[i][j][n]!=-1&&dp[i][j][n]<ans) ans=dp[i][j][n];
		printf("%d\n",ans);
	}
	return 0;
}

再次感谢bin神,axp巨巨,Tonny巨巨和群巨和广大acm爱好者的支持。

时间: 2024-10-11 05:51:08

GDUT决赛题解的相关文章

“Wishare杯”南邮第八届大学生程序设计竞赛之现场决赛 题解报告

A.爆炸吧,现充 (红) 时间限制:1000ms           内存限制:65536K 题目描述: a协有部分脱团分子,日复一日,年复一年地进行秀恩爱虐狗行为,对其他成员持续造成着精神伤害.Kojimai君表示在异端分子长期惨无人道的精神攻击下,早早的患上了少年痴呆症.为了应对这一症状,不得不经常把日常琐事记录下来,时间一长整本笔记本都记完了,他现在好奇自己一共记下了多少字,已知笔记本共n页,每页m行,因为心理因素,他排斥偶数页号,所以只在奇数页号的页面写字,又因为痴呆他在奇数页的第i行都

第十五届北京师范大学程序设计竞赛现场决赛题解

C. Captcha Cracker题目大意:给一个字符串,识别出0,2,4,6,9以及英文单词并按照出现顺序输出.通过人数/提交人数:60/62题目解法:直接模拟. F. Find Quailty题目大意:给一个凸多边形,求出从不在多边形内一点??出发走不超过??距离且不进入多边形内部所能到的区域面积.通过人数/提交人数:0/3题目解法:圆面积减去圆和凸多边形交的面积是显然不对的. 如果??不在边界上,过??作两条凸包的切线,那么区域被分为两部分,其中一部分如下图所示,只需要计算圆和简单多边形

[GDUT 决赛]--GCD,LCM——我是好人(数论)

Description 众所周知,我是好人!所以不会出太难的题,题意很简单 给你两个数n和m,问你有多少对正整数对最大公约数是n,最小公倍数是m最后友情提供解题代码(我真是太好人了) void solve() { long long n, m; scanf("%lld%lld", &n, &m); int ans = 0; for (long long i = 1; i <= m; i++) { for (long long j = i; j <= m; j

GDUT决赛 我是好人

Problem F: 我是好人 Description 众所周知,我是好人! 所以不会出太难的题,题意很简单 给你两个数n和m,问你有多少对正整数对最大公约数是n,最小公倍数是m 最后友情提供解题代码(我真是太好人了) void solve() { long long n, m; scanf("%lld%lld", &n, &m); int ans = 0; for (long long i = 1; i <= m; i++) { for (long long j

2016年 蓝桥杯决赛体验

本来想搜决赛题解的... 结果搜到了“如何评价16年蓝桥杯......”看到一众人说自己只会第一题....刚觉得安慰了许多... 然后就搜到了决赛成绩...优秀奖...完美打铁... .........看到同行的一等...二等...三等...怀疑自己的水平已经..... 说多了都是泪....已经不能理解只提交了第一题我了... 比赛的时候就感觉不想写不想写...看上去都是可以暴力过30%~50%的数据...然后暴力每每写的太丑...放弃找bug...填空题又太笨没有想出来... 就这样思考完了每

个人训练记录1

梦天退役了,队伍散了咯.得靠自己了以后.从基础重新来过吧,不能被某方面太简单的题卡题,要全面点. 5.22[kuangbing带我飞12]基础dp1.6个水题.BCEGIL. 5.23[kuangbing带我飞12]基础dp1.2个水题.FN. 5.24[kuangbing带我飞12]基础dp1.4个水题.HJOP. 5.25[kuangbing带我飞12]基础dp1.1个水题.R. 5.26[东华OJ 金马联赛网络同步资格赛](待续) 5.27 [Codeforces Round #416 (

2016广东工业大学新生杯决赛网络同步赛暨全国新生邀请赛 题解&amp;源码

Problem A: pigofzhou的巧克力棒 Description 众所周知,pigofzhou有许多妹子.有一天,pigofzhou得到了一根巧克力棒,他想把这根巧克力棒分给他的妹子们.具体地,这根巧克力棒长为 n,他想将这根巧克力棒折成 n 段长为 1 的巧克力棒,然后分给妹子们. 但是他妹子之一中的 15zhazhahe 有强迫症.若它每次将一根长为 k 的巧克力棒折成两段长为 a 和 b 的巧克力棒,此时若 a=b,则15zhazhahe会得到一点高兴值. pigofzhou想知

2015蓝桥杯决赛

五月二十八号,坐上了开往北京的火车.第一次到北京参加全国性的比赛,第六届蓝桥杯决赛,心里面还是很兴奋的,同时也有一点点紧张,还是希望自己能拿一个比较好的成绩.提前一天到,大家看了看考场,比赛地点在北大计算中心,30号下午一点开始了正式的比赛,比赛时间四个小时. 比赛题目类型和初赛差不多,有结果填空,代码填空和程序设计三种类型.但是题量少很多,一共只有六道,分别是两道结果填空,一道代码填空,三道编程大题.我参加的是C++本科A组,比赛结束了,凭印象还是先把题目总结一下. A.结果填空 题目大意:有

华南师大 2017 年 ACM 程序设计竞赛新生初赛题解

华南师大 2017 年 ACM 程序设计竞赛新生初赛题解 华南师范大学第很多届 ACM 程序设计竞赛新生赛(初赛)在 2017 年 11 月 20 日 - 27 日成功举行,共有 146 名同学有效参赛(做出 1 题).进入决赛的资格初定为完成并通过 5 题或以上,决赛时间是 12 月 3 日,地点未定. 题解 被你们虐了千百遍的题目和 OJ 也很累的,也想要休息,所以你们别想了,行行好放过它们,我们来看题解吧... A. 诡异的计数法 Description cgy 太喜欢质数了以至于他计数也