2020年10月28日普级组(校网)

Problem 1: MSWORLD

时间限制:10000MS
内存限制:256000KB


题目描述
Bessie , Farmer John 的优选牛,刚刚获得了一个牛科动物选美比赛的冠军!并得到了“世界奶牛小姐”的头衔。因此,Bessie将进行一场环球农场旅行,共N个农场(2<=N<=50,000),依次传播农场主和奶牛们之间的亲善友好。为了简单起见,世界可以看作一个二维平面,每座农场的位置用二维坐标(x,y)表示,x,y是-10,0000到10,0000的整数。没有两座农场处于同一个位置上。

哪怕Bessie在两个农场间都是走的直线,在某些农场间的距离还是很远,所以她想随身携带一只装满了干草的箱子,这样她在每一段行程都有充足的食物。因为Bessie在她每到达一个农场后都要重新装满她的箱子,她想弄清楚她可能要走的最大距离,以此来决定它必须携带多大的箱子。帮帮Bessie吧!你只要求出任意两点距离的最大值就可以了。

输入
第一行,一个整数,N。第2~N+1行,两个整数X,Y,描述了农场的坐标。

输出
一个整数,最大距离的平方。

输入样例

4
0 0
0 1
1 1
1 0

输出样例

2

样例说明
农场1(0,0)和农场3(1,1)的距离为 2的开方。

说明:
数据范围限制2<=N<=50,000

思路:
这道题我们还须知道一个前置知识:欧式距离
后知其法,乃可暴力也!
但是校网数据有问题,n=1?那我们就面向数据编程,懂?
在这里插入图片描述

#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
const int N = 5e4 + 10;
ll n, x[N], y[N], maxn = -1;
int main()
{
    
    
	scanf("%lld", &n);
	for(ll i = 1; i <= n; i++)
	{
    
    
		scanf("%lld%lld", &x[i], &y[i]);
		for(ll j = 1; j < i; j++)
			maxn = max(maxn, (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
	}
	printf("%lld", maxn);
	return 0;
}

Problem 1: SMRTFUN

时间限制:3000MS
内存限制:256000KB


题目描述
“又肥又温顺,又大又笨,他们看起来那么傻,而且也不有趣……”

这些牛想要证明,他们是既有趣,又聪明的。为了这样做,Bessie组织了一个由牛组成的展览。她有N(1<=N<=100)头牛的情况:聪明程度Si(-1000<=Si<=1000)和有趣程度Fi(-1000<=Fi<=1000)。

Bessie必须选择一些牛来参展。牛的总的聪明值TS是所有参展牛的聪明值Si的和,总的有趣值TF是所有参展牛的有趣值Fi的和。Bessie希望能使TS和TF的和最大。但是,她仍然要求TF和TS都大于等于0,因为,如果其中一个小于0的话,对这个展出将是致命的。
所以,请帮助Bessie找到最大的TS和TF的和,而且这两个数都要非负。

输入
第一行,一个整数N,牛的个数。第2~N+1行,两个整数,依次是Si和Fi。

输出
仅一行,所求得的TS和TF的和

输入样例复

5
-5 7
8 -6
6 -3
2 1
-8 -5

输出样例

8

样例说明
选择第1,3和4号牛。TS=-5+6+2=3,TF=7-3+1=5,所以,TS+TF=3+5=8。虽然,加上2号牛可以使总和变成10,但是,TF小于0,不符合要求。
说明

数据范围限制
1 < = N < = 100 1<=N<=100 1<=N<=100
( − 1000 < = S i < = 1000 ) (-1000<=Si<=1000) (1000<=Si<=1000)
( − 1000 < = F i < = 1000 ) (-1000<=Fi<=1000) (1000<=Fi<=1000

思路:
这道题我们可以把它理解成一道01背包的变式,
把S[i]看成物品重量,F[i]看成物品价值,去做背包。
那背包的容量也就出来的了,想一想,S[i]为重量,
题目S[i]给出最大为1000,N最大为100,那容量就为:
∑ i = 1 n s [ i ] \sum\limits _{i=1}^ns[i] i=1ns[i],简单点就是100000(M)
再考虑S[i]可能为负数的情况,那不就是将所有S[i]
都加个M?(超级加倍

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 1e2 + 10;
const int M = 1e5;
int n, S[N], F[N], f[N][M * 2 + 10], maxn;
int main()
{
    
    
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d%d", &S[i], &F[i]);
	memset(f, -0x3f, sizeof(f));
	f[0][M] = 0;
	for(int i = 1; i <= n; i++)
	for(int j = M + M; j >= S[i]; j--)
		f[i][j] = max(f[i - 1][j], f[i - 1][j - S[i]] + F[i]);	
	for(int j = M; j <= M * 2; j++)
		if(f[n][j] >= 0) maxn = max(maxn, f[n][j] + j - M);
	printf("%d\n", maxn);
	return 0;
}

Problem 3: 区间和的和

在这里插入图片描述
在这里插入图片描述

思路:
怎么说,就是一道找规律。
考虑一个数a(位置为i),他在子集和中出现了多少次,
不就算出他前面有多少个数(i),
算出他后面有多少个数(n-i+1),
再根据乘法原理,两数相乘
a n s = ( a n s % M o d + a ∗ ( i ∗ ( n − i + 1 ) ) % M o d ) % M o d ; ans = (ans \% Mod + a * (i * (n - i + 1)) \% Mod) \% Mod; ans=(ans%Mod+a(i(ni+1))%Mod)%Mod;

#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
const int Mod=1e9+7;
ll n, a, ans;
int main() {
    
    
	scanf("%lld", &n);
	for (ll i = 1; i <= n; i++)
		scanf("%lld", &a),
		ans = (ans % Mod + a * (i * (n - i + 1)) % Mod) % Mod;
	printf("%lld", ans % Mod);
	return 0;
}

Problem 4: 最大异域和

在这里插入图片描述
思路:
x o r xor xor值更大,肯定最好能保证两个数每一个位(二进制位)都不一样,也就是1的位置要不一样
比如: 1001 x o r 0110 = 1111 , 1001 x o r 1000 = 0001 1001 xor 0110 = 1111, 1001 xor 1000 = 0001 1001xor0110=1111,1001xor1000=0001

预 处 理 出 22 2 0 − > 20 − > 20 − > 2 3 03030 预处理出2 22 ^ 0 − > 2 0 - > 20−>2 ^ 30 3030 2220>20>20>2303030
对于每一个数,尽量选用大一些的二次方,且不可以重复使用一个二次方

#include <cstdio>
#include <iostream>
#define ll long long 
using namespace std;
const int N = 2e2 + 10;
const int M = 5e1 + 10;
ll n, ans, a[N], mi[M];
int main() 
{
    
    
	scanf("%lld", &n);
	mi[0] = 1;
	for(ll i = 1; i <= 30; i++) mi[i] = mi[i - 1] * 2;
	for(ll i = 1; i <= n; i++)
	{
    
    
		scanf("%lld", &a[i]);
		ll tot = 0;
		for(int j = 30; j >= 0; j--)
			if(tot + mi[j] <= a[i] && mi[j]) tot += mi[j], mi[j] = 0;
		ans += tot;
	}
	printf("%lld\n", ans);
}

Problem 5: 小B浇花

在这里插入图片描述
思路:
这道题我们可以贪心。
从低到高枚举花,如果此高度的花不止一朵,
就浇花到此高度的花只剩一朵,一直这样下去。
再在浇花时判断高度上限是否到顶了,
是的话就,用一遍高斯就没了。

#include <cstdio>
#include <iostream>
using namespace std;
const int N=4e4+10;
int n, a, t[N], ans;
int main()
{
    
    
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a), t[a]++;
	for(int i = 0; i <= 40000; i++)
	{
    
    
		if(t[i] > 1)
		{
    
    
			ans += t[i] - 1;
			t[i + 1] += t[i] - 1;
			if(i == 40000) ans = ans + t[i] * (t[i] - 1);
		}
	}
	printf("%d\n", ans);
	return 0;
}

Problem 6: POPULAR

题目描述
每头牛都有一个梦想:成为一个群体中最受欢迎的名牛!在一个有N(1<=N<=10,000)头牛的牛群中,给你M(1<=M<=50,000)个二元组(A,B),表示A认为B是受欢迎的。既然受欢迎是可传递的,那么如果A认为B受欢迎,B又认为C受欢迎,则A也会认为C是受欢迎的,哪怕这不是十分明确的规定。你的任务是计算被所有其它的牛都喜欢的牛的个数。

输入
第一行,两个数,N和M。第2~M+1行,每行两个数,A和B,表示A认为B是受欢迎的。

输出
一个数,被其他所有奶牛认为受欢迎的奶牛头数。
输入样例

3 3
1 2
2 1
2 3

输出样例

1

样例说明
3号奶牛是唯一被所有其他奶牛认为有名的。

说明
数据范围限制
1 < = N < = 10 , 000 ; 1<=N<=10,000; 1<=N<=10,000;
1 < = M < = 50 , 000 1<=M<=50,000 1<=M<=50,000

思路:
这道题就是一道d f s dfsdfs。
我们用邻接表储存之后,
就从每一个点开始dfs,
给每一个它喜欢的点标记。
最后我们看看有多少个点有被标记n − 1次,
那些点就是其他的牛都喜欢的牛。
最后,我们只要输出这样的点的数量,就可以了。

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 5e4 + 10;
struct node {
    
    int x, y, next;} edge[N];
int n, m, u, v, tot, hd[N], count[N], ans;
bool vis[N];
void add(int u, int v) {
    
    edge[++tot] = (node){
    
    u, v, hd[u]}, hd[u]=tot;}
void dfs(int u) {
    
    
	vis[u] = 1;
	for (int i = hd[u]; i; i = edge[i].next)
	{
    
    
		int v = edge[i].y;
		if (!vis[v]) count[v]++, dfs(v);
	}
}

int main() {
    
    
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) scanf("%d%d", &u, &v), add(u, v);
	for (int i = 1; i <= n; i++) memset(vis, 0, sizeof(vis)), dfs(i);
	for (int i = 1; i <= n; i++)
		if (count[i] == n - 1) ans++;
	printf("%d", ans); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bigwinner888/article/details/109343544
今日推荐