第十一届河南省程序设计大赛----部分题解

第十一届河南省程序设计大赛----部分题解

A B F D H C (由易到难

题目链接:http://nyoj.top/web/contest/show/cid/103

A计划日

题目描述:
打造名校进阶计划,让孩子会学习、会考试,实现名校梦想!
Dr. Kong, 作为一名从教多年的老师,跟踪了大量成绩好的学生,发现他们的学习习惯非常规律,有方法、有计划、有目标、有总结。比如:已考上**大学的李明同学,从小学开始订学习计划,达成目标。每经过N天就检查目标是否完成,写总结,并确定下一个学习目标。
已知李明在YYYY年MM月DD日星期W订了学习计划,现在想看看李明N天后的完成情况和个人总结,你能告诉我那天的日期和星期几吗?
输入描述:
第一行: T 表示以下有T组测试数据( 1≤ T ≤8 )对每组数据, 占一行:
YYYYMMDD W N(20000101≤YYYYMMDD≤20180527 1≤W≤ 7 1 ≤N≤ 8000 )
输出描述:
对每组测试数据,输出占一行,格式为:YYYYMMDD W ( 中间一个空格 )
样例输入:
2
20180527 7 1
20180214 3 289
样例输出:
20180528 1
20181130 5

签到题,模拟 ,注意细节
(我用了计算星期的公式 ,其实可以不用,题目已经告诉了开始日期是星期几,递推就好了)

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int leep[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},
                {0,31,29,31,30,31,30,31,31,30,31,30,31}};
int check(int year){
    return ((year%4==0&&year%100!=0)||year%400==0);
}
int T,s,w,n,day,month,year;
void week(){
	if(month<3){ month+=12;year--; }
	w= (day+2*month+3*(month+1)/5+year+year/4-year/100+year/400+1)%7;
	if(w==0)cout<<"7"<<endl;
	else 	cout<<w<<endl;
}
int main(){
	cin>>T;
	while(T--){
		cin>>s>>w>>n;
		day=s%100;s/=100;
		month=s%100;s/=100;
		year=s;
		while(n>leep[check(year)][month]-day){
			n-=leep[check(year)][month]-day;
			if(month<12)month++;
			else { month=1;year++; }
			day=0;
		}
		day+=n;
		printf("%d%02d%02d ",year,month,day);
		week();
	}
	return 0;
}

B治安管理

为了维护SZ经济特区社会治安秩序,保障特区改革开放和经济建设的顺利进行, 特别设立了SZ社会治安综合治理委员会主管特区的社会治安综合治理工作。公安机关是社会治安的主管部门,依照法律、法规的规定进行治安行政管理,打击扰乱社会治安的违法犯罪行为,维护社会秩序。
YYH大型活动将在[S,F)这段时间举行,现要求活动期间任何时刻巡逻的警察人数不少于M人。公安机关将有N名警察在维护活动的安全,每人巡逻时间为[ai,bi)。请你检查目前的值班安排,是否符合要求。若满足要求,输出YES,并输出某个时刻同时巡逻的最多人数;若不满足要求,输出NO,并输出某个时刻同时巡逻的最少人数。
输入描述:
第一行: T 表示以下有T组测试数据( 1≤ T ≤5 )
对每组数据,
第一行:N M S F ( 1≤N≤10000 1≤M ≤1000 0≤S<F≤100000)
第二行,a1 a2 …. an 警察巡逻起始时间
第三行,b1 b2 …. bn 警察巡逻结束时间 ( 0≤ai0 i=1…. n)
输出描述:
对每组测试数据,输出占一行。若满足要求,输出YES,并输出某个时刻同时巡逻的最多人数;若不满足要求,输出NO,并输出某个时刻同时巡逻的最少人数。(中间一个空格)
样例输入:
2
5 2 0 10
0 0 2 7 6
6 2 7 10 10
10 2 6 11
1 3 5 7 9 2 4 6 8 10
2 4 6 8 10 3 5 7 9 11
样例输出:
YES 2
NO 1

签到题,暴力做法:给每个人执勤区间都加1,最后扫一遍,拿最大、最小。
暴力的复杂度是O(N*F),根据题目范围,复杂度是1e9,这个复杂度太高了,但是后台数据太水了,暴力也能过
其实不暴力的话,还有个O(n)的解法:
用一维数组模拟时间轴,某个人执勤的时间是[ai,bi),那么就在数组a[ ai ]累加1 ,a[bi]累加 -1
最后对整个数组 ,遍历累加,累加过程中的值就是此时刻的执勤人数。复杂度O(F)

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1e5+7;
const int INF=0x3f3f3f3f;
int a[maxn];
int T,n,m,s,f,x;
int main(){
	cin>>T;
	while(T--){
		memset(a,0,sizeof(a));
		cin>>n>>m>>s>>f;
		for(int i=1;i<=n;i++){
			cin>>x;a[x]++;
		}
		for(int i=1;i<=n;i++){
			cin>>x;a[x]--;
		}
		int cnt=0;
		int minn=INF,maxx=-1;
		for(int i=0;i<f;i++){
			cnt+=a[i];
			if(i>=s&&i<f){
				if(cnt<minn&&cnt!=0)minn=cnt;
				if(cnt>maxx)maxx=cnt;
			}
		}
		if(minn<m) printf("NO %d\n",minn);
		else printf("YES %d\n",maxx);
	}
	return 0;
}

F Gene mutation

题目描述:
Gene mutation is the sudden and inheritable mutation of genomic DNA molecules. From the molecular level, gene mutation refers to the change of the composition or sequence of base pairs in the structure of a gene. Although the gene is very stable, it can reproduce itself accurately when the cell divides. Under certain conditions, the gene can also suddenly change from its original existence to another new form of existence.
A genome sequence might provide answers to major questions about the biology and evolutionary history of an organism. A 2010 study found a gene sequence in the skin of cuttlefish similar to those in the eye’s retina. If the gene matches, it can be used to treat certain diseases of the eye.
A gene sequence in the skin of cuttlefish is specified by a sequence of distinct integers (Y1,Y2, …Yc). it may be mutated. Even if these integers are transposed ( increased or decreased by a common amount ) , or re-ordered , it is still a gene sequence of cuttlefish. For example, if “4 6 7” is a gene sequence of cuttlefish, then “3 5 6” (-1), “6 8 9” ( +2), “6 4 7” (re-ordered), and “5 3 6” (transposed and re-ordered) are also ruminant a gene sequence of cuttlefish.
Your task is to determine that there are several matching points at most in a gene sequence of the eye’s retina (X1,X2, …, Xn)
输入描述:
The first line of the input contains one integer T, which is the number of test cases (1<=T<=5). Each test case specifies:
Line 1: n ( 1 ≤ n ≤ 20,000 )
Line 2: X1 X2… Xn ( 1 ≤ Xi ≤ 100 i=1…. n)
Line 3: c ( 1 ≤ c ≤ 10 )
Line 4: Y1 Y2… Yc ( 1 ≤ Yi ≤ 100 i=1…. c)
输出描述:
For each test case generate a single line: a single integer that there are several matching points. The matching gene sequence can be partially overlapped
样例输入:
1
6
1 8 5 7 9 10
3
4 6 7
样例输出:
2

签到题,双重for循环,暴力对比

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1e5+7;
const int INF=0x3f3f3f3f;
int T,res,n,m;
int a[maxn],b[20],f[20];
int main(){
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=0;i<n;i++)cin>>a[i];
		cin>>m;
		for(int i=0;i<m;i++)cin>>b[i];
		sort(b,b+m);
		
		for(int i=0;i<n-m+1;i++){
			int cnt=0;
			for(int j=i;j<i+m;j++){
				f[cnt]=a[j];cnt++;
			}
			sort(f,f+m);
			int flag=0,ans=0;
			for(int i=0;i<m;i++){
				if(i==0) ans=f[i]-b[i];
				else if(ans!=f[i]-b[i]){
					flag=1;break;
				}
			}
			if(flag==0)res++;
		}
		cout<<res<<endl;
		res=0;
	}
	return 0;
}

D 求XF+闭包

题目描述:
如何设计一个好的数据库不仅仅是一个理论研究问题,也是一个实际应用问题。在关系数据库中不满足规范化理论的数据库设计会存在冗余、插入异常、删除异常等现象。
设R(U)是一个关系模式,U={ A1,A2, ……, An}。其中Ai是关系的属性,X,Y是U的子集。函数依赖 X->Y 定义了数据库中属性集X与Y的依赖关系。根据Armstrong公理,函数依赖满足:
(1) 自反律:若Ai∈X, 则 X->Ai . 特别地,Ai ->Ai .
(2) 增广律:若 X->Y, 则 ZX->ZY. (ZX 是指集合Z与X的并集 )
(3) 传递律:若 X->Y, Y->Z, 则 X->Z.
(4) 分解律:若 X->Y, 则 X->Ai ( 若属性Ai∈Y )
(5) 合并律:若 X->Y, X->Z, 则 X->YZ.
已知 F 是关系模式R(U)上的函数依赖集,利用Armstrong公理系统可以推导出更多的函数依赖。设X是属性集U={ A1,A2, ……, An} 的子集, 定义X关于F的闭包XF+
XF+={ Ai | 若X->Ai可以通过Armstrong公理导出}
对于给定的U , F ,X, 请求出XF+
输入描述:
第一行: T 表示以下有T组测试数据( 1≤T ≤5 )
对每组数据,
第1行: n m k n 表示U中属性个数( 1≤n≤26 ), 用大写字母表示 。m表示X中属性个数( 1≤m≤26 ),k个函数依赖 (1≤ k ≤ 20 )。
第2行: 字符串U n个大写字母
第3行: 字符串X m个大写字母
接下来有K行,每行有两个字符串 S T,用一个空格隔开。 表示 S->T
输出描述:
对每组测试数据,输出占一行输出XF+,要求按字母序输出。
样例输入:
1
6 2 4
ABGDCI
AD
A B
BD I
AG C
C D
样例输出:
ABDI

这题是铜牌题,然而还是暴力,果然去年的省赛就是-----暴力出奇迹,
这题关键是把题目有读懂,题目不是很直白(可能这就是他是铜牌题的原因吧)
不过可以猜样例啊,结合样例,不难看出,题目的意思其实就是,先给你两个字符串U(这个没用),X。
然后每次给你两个字符串a和b,只要a是X的子集,那么就把b也加入X。然后问最终的X是什么。
暴力,扫a加b就好了。
注意,一遍遍历是不够的,可能第一个a不是X的子集,但是通过后边数据给X扩充后,开头的a又是X的子集了。所以,我们需要扫描多遍才能保证完成题意。最多20遍。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1e5+7;
const int INF=0x3f3f3f3f;
int n,m,k,T;
string u,x;
int cnt[29];
int main(){
	cin>>T;
	while(T--){
		cin>>n>>m>>k;
		cin>>u>>x;
		memset(cnt,0,sizeof(cnt));
		for(int i=0;i<x.size();i++)cnt[x[i]-'A'+1]=1;
		string a[22],b[22];
		for(int i=1;i<=k;i++){
			cin>>a[i]>>b[i];
		}
		int num=20;
		while(num--){
			int flag=0;
			for(int i=1;i<=k;i++){
				flag=0;
				for(int j=0;j<a[i].size();j++){
					if(cnt[a[i][j]-'A'+1]==0){
						flag=1;break;
					}
				}
				if(flag==0){
					for(int j=0;j<b[i].size();j++){
						cnt[b[i][j]-'A'+1]++;
					}
				}
			}
		}
		for(int i=1;i<=26;i++){
			if(cnt[i]!=0)printf("%c",i+'A'-1);
		}printf("\n");
	}
	return 0;
}

H Attack City and Capture Territory

这题是银牌题
题目就不放了,就是个裸的Nim博弈,怪不得大佬们直接一发ac。。。。。。
放个Nimm博弈的博客:https://blog.csdn.net/holly_Z_P_F/article/details/82083635

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1e5+7;
const int INF=0x3f3f3f3f;
int T,n,x,ans;
int main(){
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>x;
			if(i==1)ans=x;
			else ans^=x;
		}
		if(ans==0) cout<<"Liu_B is not sure to win."<<endl;
		else cout<<"Liu_B is sure to win."<<endl;
	}
	
	return 0;
}

C 山区修路

题目描述:
最近,HB省决定修一条从YC市通往SNJ风景区的高速公路。经过勘测分析,途中需要经过高度分别为H1,H2,……,Hn的N个山区。由于高低不平,除正常的修路开支外,每段还要多出高度差| H[i] - H[i-1] |*X万元的斜坡费用。Dr. Kong 决定通过填高一些区域的高度来降低总的费用。当然填高也是需要一些费用的。每填高Y单位,需要付出Y^2万元费用。
你能否帮Dr. Kong做出一个规划,通过部分填高工程改造,使得总的费用降下来。
输入描述:
第一行: T 表示以下有T组测试数据( 1≤ T ≤8 )
对每组测试数据,
第一行:N X(2 ≤ N ≤100,000 1≤ X ≤100)
第二行:N个整数,分别表示N个区域的高度Hi( 1<=Hi<=100 , i=1…. n)
输出描述:
对每组测试数据,输出占一行,一个整数,即经过部分填高工程改造后的最少费用。
样例输入:
1
5 2
2 3 5 1 4
样例输出:
15

动态规划,dp[i][j]代表第i座山高度为j的时候,前 i 座山的最小总花费
三重循环dp,比赛的时候数据比较水,可以过。
随后南阳理工的重现题数据加强了,三重循环过不了。在网上看到大佬用寄存器优化才过
关于寄存器:https://blog.csdn.net/holly_Z_P_F/article/details/89787424
(这题做了还是银,可能是数据太水的原因,7道题才能金)

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define re register//寄存器 
int T,n,x,flag;
const int maxn=1e5+7;
int dp[maxn][107];
int a[maxn];
const int INF=0x3f3f3f3f;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&x);flag=0;
        for(re int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]>flag)flag=a[i];
        }
        for(re int i=a[1];i<=flag;i++)dp[1][i]=(i-a[1])*(i-a[1]);
        for(re int i=2;i<=n;i++){
            for(re int j=a[i];j<=flag;j++){
                dp[i][j]=INF;
                for(re int k=a[i-1];k<=flag;k++){
                    dp[i][j]=min(abs(k-j)*x+dp[i-1][k]+(j-a[i])*(j-a[i]),dp[i][j]);
                }
            }
        }
        int ans=INF;
        for(re int i=a[n];i<=flag;i++){
            if(dp[n][i]<ans)ans=dp[n][i];
        }
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1900_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值