2020.02.09【NOIP普及组】模拟赛C组

0【普组模拟赛】马农(farmer.pas/cpp)
1【普组模拟赛】马语翻译(trans.pas/cpp)
2【普组模拟赛】马球比赛(polo.pas/cpp)
3【普及模拟】数列(sequence.pas/cpp)

T1

题目描述

      在观看完战马检阅之后,来自大草原的两兄弟决心成为超级“马农”,专门饲养战马。
      兄弟两回到草原,将可以养马的区域,分为 N*N 的单位面积的正方形, 并实地进行考察,归纳出了每个单位面积可以养马所获得的收益。接下来就要开始规划他们各自的马场了。
      首先,两人的马场都必须是矩形区域。同时,为了方便两人互相照应,也为了防止马匹互相走散,规定两个马场的矩形区域相邻,且只有一个交点。最后,互不认输的两人希望两个马场的收益相当,这样才不会影响他们兄弟的感情。
      现在,兄弟两找到你这位设计师,希望你给他们设计马场,问共有多少种设计方案。

输入

第一行一个整数 N,表示整个草原的大小为 N*N。
接下来 N 行,每行 N 个整数 A(i,j),表示第 i 行第 j 列的单位草地的收成。
(注意:收益可能是负数,养马也不是包赚的,马匹也可能出现生病死亡等意外。)

输出

输出符合两人要求的草原分配方案数。

样例输入

3
1 2 3
4 5 6
7 8 9

样例输出

2

【样例解释】

数据范围限制

【数据范围】
40%的数据, N<=10。
100%的数据, N<=50, -1000<A(i,j)<1000。

O(N^4)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long f[2001][2001],a[2001][2001],d[5000001],n,ans;
int main(){
	freopen("farmer.in","r",stdin);
	freopen("farmer.out","w",stdout);
	memset(f,0,sizeof(f));
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++){
		scanf("%lld",&a[i][j]);
		f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];	
	}
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++){
		for(int x=1;x<=i;x++)
		for(int y=1;y<=j;y++)
			d[f[i][j]-f[i][y-1]-f[x-1][j]+f[x-1][y-1]]++;
		for(int x=i+1;x<=n;x++)
		for(int y=j+1;y<=n;y++)
			ans+=d[f[x][y]-f[x][j]-f[i][y]+f[i][j]];
		for(int x=1;x<=i;x++)
		for(int y=1;y<=j;y++)
			d[f[i][j]-f[i][y-1]-f[x-1][j]+f[x-1][y-1]]=0;
		
		for(int x=1;x<=i;x++)
		for(int y=j+1;y<=n;y++){
			d[f[i][y]-f[x-1][y]-f[i][j]+f[x-1][j]]++;
		}
		for(int x=i+1;x<=n;x++)
		for(int y=1;y<=j;y++)
			ans+=d[f[x][j]-f[i][j]-f[x][y-1]+f[i][y-1]];
		for(int x=1;x<=i;x++)
		for(int y=j+1;y<=n;y++)
			d[f[i][y]-f[x-1][y]-f[i][j]+f[x-1][j]]=0;
	}
	printf("%lld",ans);
	return 0;
}

T2

题目描述

      随着马场的繁荣,出现了越来越多的新马种。种族之间的沟通不畅严重影响了马场的和谐。这时,科学家发明了马语翻译机器人,正好可以解决这一难题。
      机器人有 M 种,每种机器人能完成 K 个马种之间的语言翻译。问,利用这些机器人,能否实现 1 种群和 N 种群的马语翻译。 若可以,找到翻译过程至少需要用到多少种语言。

输入

  第一行三个整数 N, K 和 M,分别表示语言数, 每个机器人能翻译的语言数, 机器人的数量。
  接下来 M 行,每行 K 个整数。表示每个机器人可以翻译的语言编号(编号从 1 到 N)。

输出

输出最少转换语言的次数。如果无法完成翻译,输出-1。

样例输入

9 3 5
1 2 3
1 4 5
3 6 7
5 6 7
6 8 9

样例输出

4

【样例解释】

1-3-6-9 或者 1-5-6-9

数据范围限制

【数据范围】
40%的数据 N<=100, 1<=K<=20, M<=40。
100%的数据 1<=N<=100000, 1<=K<=1000, 1<=M<=1000。

dij的板题

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long dis[100100];
int n,m,k,a[2000][2000];
void spfa(){
	long long f=1;
	memset(dis,0x3f,sizeof(dis));
	dis[1]=1;
	while(f!=0){
		f=0;
		for(int i=1;i<=m;i++){
			long long minn=0x3ffffff,bz=0x3fffffff;
			for(int j=1;j<=k;j++)
				if(dis[a[i][j]]<minn)
				   minn=dis[a[i][j]];
			if(minn==bz)continue;
			for(int j=1;j<=k;j++)
			    if(dis[a[i][j]]>minn+1)
				   dis[a[i][j]]=minn+1,f=1; 
		}
	}
}
int main(){
	freopen("trans.in","r",stdin);
	freopen("trans.out","w",stdout);
	cin>>n>>k>>m;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=k;j++)
            cin>>a[i][j];
    spfa();
    if(dis[n]==dis[0])cout<<-1;
	else cout<<dis[n];
}

T3

题目描述

        在解决了马语翻译问题后,马匹数量越来越多,不少乡镇都有了数量可观的马匹,开始出现马球比赛。乡镇之间决定进行马球联赛。
        联赛的赛制,主要是比赛双方的马匹数量,成了一个急需解决的问题。首先,所有乡镇都要求,本乡镇所有的马匹都必须参赛,或者都不参赛(若组队的马匹数量不是该镇马匹数量的约数,将无法参赛)。其次,在本乡镇,选出最佳球队,参加乡镇间联赛。
        现在,比赛组织方希望满足所有参赛乡镇的要求,并且使得决赛的马匹尽可能多,请你设计每个球队马匹的数量,使得决赛马匹数最大。注意,决赛至少有 2 个队伍晋级。

输入

第一行一个整数 N,表示想要报名参赛的乡镇。
接下来 N 个用空格分开的整数 a(i),表示第 i 个乡镇报名参赛的马匹数。

输出

计算出决赛最大参与的马匹数。

样例输入

【输入样例 1】
3 1 3 6

【输入样例 2】

5 4 6 3 8 9

样例输出

【输出样例 1】
6

【样例解释】

 每个队伍 3 匹马,乡镇 1 无法参赛。乡镇 2 和 3 都可以进行比赛,决赛 2 个队伍,共 6匹马。

【输出样例 2】

9

【样例解释】

每个队伍 3 匹马,乡镇 2,3,5 可以参赛。决赛 3 个队伍, 9 匹马。

数据范围限制

【数据范围】
20%的数据 2<=N<=100, 1<=a(i)<=10000。
50%的数据 2<=N<=20000。
100%的数据 2<=N<=200000, 1<=a(i)<= 2000000。

f[i]表示以i为人数的队伍数
我们先把最大的数找出来,在1~max中枚举可能的人数,然后我们用递推,从2到sqrt(i),找到i的因数,这时有两种可能:
1.f[j]+=f[i]
2.j的因数k,f[k]+=f[i]
这样一来事情决绝

#include<iostream>
#include<cstdio>
using namespace std;
long long m,n,k,x,y,f[4000000];
int main(){
	freopen("polo.in","r",stdin);
	freopen("polo.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>k;
		f[k]++;
		m=max(k,m);
	}
	for(int i=1;i<=m;i++){
		if(f[i]!=0)
		for(int j=2;j*j<=i;j++){
			if(i%j==0){
				if(i!=j)f[j]+=f[i];
				if(j*j!=i)f[i/j]+=f[i];
			}
		}
	}
	for(int i=1;i<=m;i++){
		if(f[i]>1)//两个队以上
		x=max(f[i]*i,x);
	}
	cout<<x;
	return 0;
}

T4

题目描述

给定一个长度为N的数列,求一段连续的子数列满足该子数列中的各元素的平均数大于A,输出可行方案的总数。

输入

 第一行两个整数N,A
 接下来N个整数,代表数列的N个元素。

输出

一个整数,即可行的方案数。

样例输入

5 1
1 2 3 4 5

样例输出

14

数据范围限制

数据规模
 对于60%的数据 N <= 1000
对于100%的数据 N <= 100000
所有数据包括都在longint范围内。

%60

#include<iostream>
#include<cstdio>
using namespace std;
long long m,n,k,a[1000100],b[1000100];
int main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i]-=k;
		b[i]=b[i-1]+a[i];
	}
	k=0;
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++){
			if(b[j]-b[i-1]>0)k++;
		}
	}
	cout<<k;
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值