2020.03.28【NOIP普及组】模拟赛C组21

题目编号标题
0羊羊整除(div)
1羊羊吃草(eat)
2羊羊修路(road)
3羊羊列队(queue)

鼠牛虎兔龙蛇马羊猴鸡狗猪……

T1

题目描述

羊年到了,村长开始教小羊学习Pascal语言,刚开始学习四则运算。村长在白板上写下两个整数16和3,问小羊们,有16只羊,平均分到3个羊村,每个羊村分到的数量必须相同,这个分配的数量最大是多少?小羊们很快就得到了答案,每个羊村分到5只,有1只羊就只能落单了。村长在白板上写下5。没错,这个就是Div(整除)的用法!
为了检验小羊们是否掌握了整除运算,村长要求小羊们轮流从白板上任意选取两个不同的数,由大数整除小数,若所得结果没有出现在白板上,就将该值写在白板上。直到小羊们再也找不到没出现过的整数。
虽然这样上课很锻炼小羊们的运算能力,但是课堂时间有限。为了控制课堂时间,村长想要知道,根据当前白板上的数字,最终白板上会出现几个数字?现在请你帮他编写一个程序快速计算一下吧!

输入

第一行一个整数N,表示当前白板上出现的整数个数。
第二行N个整数,中间用空格分隔,表示当前在白板上的数字,保证每个数字都不相同。

输出

输出一个整数,表示最终白板上数字的个数。

样例输入

【样例输入1】
2
16 3
【样例输入2】
3
17 2 1

样例输出

【样例输出1】
4
【样例输出2】
5

数据范围限制

50%的数据,N<=50;
100%的数据,N<=100,1<=ai<=100。

提示

【样例1解释】
   选择16和3,写下5;选择5和3,写下1;共16,3,5,1,四个整数。

【样例2解释】
选择17和2,写下8;再选择8和2,写下4;共17,2,8,4,1,五个整数。

爆力即可,必用downto

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[10001],m;
int main(){
	freopen("div.in","r",stdin);
	freopen("div.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		a[x]=1;
	}
	for(int i=100;i>=1;i--){
		if(a[i]!=0){
			for(int j=i-1;j>=1;j--){
				if(a[j]!=0){
					a[i/j]=1;
				}
			}
		}
	}
	for(int i=1;i<=100;i++)if(a[i]==1)m++;
	cout<<m;
	return 0;
}

T2:

题目描述

小羊们上完课后,纷纷到草场上吃草。而羊村现在正在进行特色示范羊村检查,领导们想看看羊村的草场。
羊村的草场是连续分布的,每块草场上都有数量不等的羊在吃	草。领导们想要查看连续若干个草场,但是又不想看到超过T只羊。而村长希望领导们多看看羊村的风貌,尽可能多参观几个草场。
现在,请你帮村长决定,带领导们去参观哪一段草场,满足领导和村长的要求。

输入

第一行一个整数N和T,表示羊村共有多少个连续草场,以及领导们希望看到羊数量的最大值。
第二行N个整数,两个整数间用一个空格分开,第i个数ai表示第i个草场上有ai只羊在吃草。编号从1到N。

输出

输出一行,共两个数,表示参观的起点编号和终点编号,中间用空格分开。走的方向总是从编号小的到编号大的。另外,若有长度相同的可能性,输出起点编号较小的答案。数据保证至少有答案存在。

样例输入

5 10
6 3 2 1 7

样例输出

2 4

数据范围限制

30%的数据,1<=N<=100;
60%的数据,1<=N<=1000;
100%的数据,1<=N<=100000, 0<=ai<=10^9,0<=T<=2^31-1。

提示

要满足连续个总和不超过10,有3+2+1和2+1+7两种可能性,优先输出2到4个草场。

……

#include<iostream>
#include<cstdio>
using namespace std;
long long m,n,k;
int a[1001000];
int main(){
	freopen("eat.in","r",stdin);
	freopen("eat.out","w",stdout);
	cin>>n>>m;
	long long l=1,r=0,maxx=0,q=0,p=0;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		maxx+=a[i];
		r++;
		if(r-l+1>k&&maxx<=m){
			k=r-l+1;
			q=l;
			p=r;
		}
		while(maxx>m){
			maxx-=a[l];
			l++;
		}
		if(r-l+1>k){
			k=r-l+1;
			q=l;
			p=r;
		}
	}
	cout<<q<<' '<<p;
	return 0;
}

T3:

题目描述

经过特色示范羊村检查,检查组觉得羊村的道路需要重修,破败的道	路,会影响到小羊们上学的安全。
村长组织施工队,开始丈量距离,规划施工方案,已经得到了若干建筑物间修建道路的可行方案,共有N个建筑物,和M条可选道路。这些路保证可以将N个建筑相连。
最终方案中,羊村打算修建全球最豪华的全大理石道路,道路可以双向通行,且一体成型,路中无缝隙。为了达到这个设计要求,就必须自建大理石工厂!
大理石工厂建造的难度在于,必须根据其需要生产最大长度的大理石来设计。工厂可以生产出不超过其设计极限的任意长度的大理石。例如,设计长度为100的工厂,可以生产100、90等长度的大理石,但是不能生产长度为101的大理石。
羊村的预算有限,希望你能帮忙规划出一个修路方案,使得工厂的设计规模尽可能小,且可以保证其能生产的大理石可以连通所有羊村的建筑。求出工厂的最小设计规模。

输入

第一行两个整数N和M,N表示羊村中的建筑数量,M表示可以修建的道路数量。
接下来M行,每行三个整数Ai,Bi和Ci,表示从建筑Ai,到建筑Bi,可以修建一条长度为Ci的道路。
注意,建筑编号从1到N,两个建筑之间可能有多条道路。

输出

输出大理石工厂的最小设计规模。

样例输入

3 3
1 2 100
2 3 101
1 3 99

样例输出

100

数据范围限制

30%的数据N<=10,N-1<=M<=100。
100%的数据1<=N<=2000,N-1<=M<=10000,1<=Ai,Bi<=N,	1<=Ci<=1000000000。

提示

只要修建1到2,以及1到3的道路,就可以使得3个建筑相互连通,且最大值只有100,只需要建造设计规模为100的大理石工厂,就可以生产出长度为100和99的大理石。

最小生成树模板:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long m,n,dis[10000],v[10000],head[10000],tot;
struct node{
	int to,next;
	long long w;
}b[100010];
void ljb(int x,int y,long long w){
	tot++;
	b[tot].to=y;
	b[tot].w=w;
	b[tot].next=head[x];
	head[x]=tot;
}
int main(){
	freopen("road.in","r",stdin);
	freopen("road.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x;int y;
		long long w;
		cin>>x>>y>>w;
		ljb(x,y,w);
		ljb(y,x,w);
	}
	memset(dis,100,sizeof(dis));
	dis[1]=0;
	int x=1,maxx=0;
	for(int i=1;i<=n;i++){
		int minn=1010100100;
		for(int j=1;j<=n;j++){
			if(v[j]==0&&minn>dis[j]){
				minn=dis[j];
				x=j;
			}
		}
		v[x]=1;
		maxx=max(maxx,minn);
		for(int j=head[x];j;j=b[j].next){
			int y=b[j].to;
			if(dis[y]>b[j].w&&v[y]==0){
				dis[y]=b[j].w;
			}
		}
	}
	cout<<maxx;
	return 0;
}

T4:

题目描述

在修建完新路后,小羊们总算可以安心入学了。今年是羊年,新入学的小羊特别多。老师们打算将N只小羊分成M个班级,每个班至少有1只羊。
如何分班成了老师们最头疼的事情,因为开学典礼上,村长就要看到小羊们列队的情况。每个班的小羊都排成一排,站在草场上。村长希望队列中羊的高度尽可能整齐,村长对队列的不整齐度有自己的要求。
例如队列中共有t只羊,高度依次为A1,A2……,At。那么不	整齐度为:(|A1-A2|+|A2-A3|+……+|At-1-At|)^2。即相邻两只羊高度差之和的平方。
而总体的不整齐度,就是各班不整齐度之和。
现在,请你帮助老师们设计一下,如何分班,如何列队,才能使M个班级的不整齐度之和最小。

输入

第一行两个整数N和M,分别表示共有N只小羊,要被分成M个班级。
第二行N个整数,表示每只小羊的高度Ai。

输出

输出最小的不整齐度之和,结果保证不会超过2^31-1。

样例输入

4 2
4 1 3 2

样例输出

2

数据范围限制

30%的数据,1<=N<=10;1<=M<=5;
80%的数据,1<=N<=300;1<=Ai<=1000;
100%的数据,1<=N<=10000,1<=M<=1000,1<=Ai<=1000000,保证M<=N。

提示

分成两班,4和3一个班,1和2一个班,不管怎么排,两个班的不整齐度都是1,不整齐度之和为2。

DPDPDPDPDPDPDPDP
设f[i][j]为第i个数前,分成j队的最小不整齐度
我们要做一个前差和,记住,是i到j之间两两的差!
f[i][j]=min(f[i][j],f[k][j-1]+b[k+1][i]);
80分
至于斜率优化,去死吧

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int m,n,k,a[10010],f[1000][1000],b[1000][1000];
int main(){
	freopen("queue.in","r",stdin);
	freopen("queue.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++){
		int sum=0;
		for(int j=i+1;j<=n;j++){
			sum+=a[j]-a[j-1];
			b[i][j]=sum*sum;
		}
	}
	memset(f,1,sizeof(f));
	for(int i=0;i<=n;i++){
		f[i][1]=b[1][i];
		f[i][i]=0;
		f[i][0]=0;
		f[0][i]=0;
		for(int j=i+1;j<=n;j++)f[i][j]=0;
	}
	for(int i=2;i<=n;i++)
	for(int j=2;j<i;j++){
		if(j>m)continue;
		for(int k=j-1;k<i;k++){
			f[i][j]=min(f[i][j],f[k][j-1]+b[k+1][i]);
		}
	}
	cout<<f[n][m];
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值