qbxt国庆水题记day1

#qbxt国庆水题记#
#day1#


//弱弱的我今天爆0了
//QAQ


##Problem 1. alien##
Input file: alien.in
Output file: alien.out
Time limit: 1s
Memory limit: 128M
小 Y 最近正在接受来自 X3 星球的外星人的采访。在那个星球上,每个人的名字都是一个正整数。
所有在这个星球上的居民都是相互认识的。两个这个星球上的⼈的友谊值可以用这样来计算: 先把两个人
的名字转换成二进制,然后把他们上下对齐排好,如果同一列的值相等,那么相应列的值就是 0,否则的
话就是 1,结果最后仍旧转换成十进制数。(即 Xor 操作)
例如,两个人的名字是 19 和 10,他们的友谊值是 25
这个星球的价值是这么计算的: 所有友情值的和。小 Y 邀请你帮助他来计算这个值。
Input
输入文件第一行一个整数 N, 表示这个星球上的总人口。
接下来 N 行,每行一个正整数,表示每个居民的姓名。
Output
输出文件一行一个整数,表示这个星球的价值。
Example

alien.inalien.out
225
19
10
-------
312
7
3
5
-------
584
9
13
1
9
6

Scoring

• 对于 40% 的数据,N ≤5000。
• 对于 70% 的数据,N ≤100000。
• 对于 100% 的数据,N ≤106, 每个居民的姓名小于 106。

解析
按位处理
统计每一位有多少1和0
然后根据1 ^ 0 = 1可以知 这一位的贡献为1和0的个数的乘积(乘法原理)
//QAQ表示看错了题思路完全错了

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 1000000 + 100;
long long  n,j,k,x,a[maxn];

int main() {
	freopen("alien.in","r",stdin);
	freopen("alien.out","w",stdout);
	cin>>n;
	for(int i = 1; i <= n; i++) {
		scanf("%d",&x);
		j = 0;
		while(x > 0) {
			j++;
			a[j] = a[j] + x % 2;
			x /= 2;
		}
		if(j > k) k = j;
	}
	long long ans = 0;
	for(int i = k; i >= 1; i--) {
		ans = ans * 2 + a[i] * (n - a[i]);
	}
	cout<<ans<<endl;
	return 0;
}

##Problem 2. polyline##
Input file: polyline.in
Output file: polyline.out
Time limit: 1s
Memory limit: 128M
有若干个类似于下面的函数:
这里写图片描述
定义 n 个函数 y1(x), …, yn(x) 的对于任意 x 的总和 s(x) = y1(x) + … + yn(x),很容易发现
图象是多段线组成。给你 n 个函数,你的任务是找出 s(x) 图象不等于 180 度的角的个数。
Input
第一行一个整数 n,表示函数的个数。
接下来 n 行, 每行包含两个空格隔开的整数 ki, bi, 表示第 i 个函数的参数。
Output
输出一行一个整数, 表⽰形成的多段线的图像中不等于 180 度角的个数。
Example
polyline1.in
1
1 0
polyline1.out
1

polyline2.in
3
1 0
0 2
-1 1
polyline2.out
2

polyline3.in
3
-2 -4
1 7
-5 1
polyline3.out
3

Scoring

• 对于 30% 的数据,n ≤3000。
• 对于 100% 的数据,1 ≤n ≤105, −109 ≤ki, bi ≤109。

由题可以得到
si = (k1 + k2 + …… + kn) * x + (b1 + b2 + …… bn)
所以如果不是180度,那斜率会改变
所以找拐点即可
但求斜率可能会卡精度,好像要开到1e-18才行,因为可以用分数表示
//当时想到了拐点,但想的太多导致出现了错误

斜率做法
代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn = 100000 + 100;
int n,ans,tot = 0;
long long k[maxn], b[maxn];
long double c[maxn];

int main() {
	freopen("polyline.in","r",stdin);
	freopen("polyline.out","w",stdout);
	cin>>n;
	for(int i = 1; i <= n; i++) {
		tot++;
		cin>>k[tot]>>b[tot];
		if(k[tot] == 0) tot--;
		else c[tot] = -((long double) b[tot] / (long double) k[tot]);
	}
	if(tot == 0) {
		cout<<0<<endl;
		return 0;
	}
	sort(c+1,c+1+tot);
	ans = tot;
	for(int i = 2; i <= tot; i++) {
		if(fabs(c[i] - c[i-1]) < 1e-18) {
			ans--;
		}
	}
	cout<<ans;
	return 0;
}

分数做法
代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn = 100000 + 100;
int n,ans,tot = 0;
long long k[maxn], b[maxn];
int vis[maxn];
long double c[maxn];

long long gcd(long long a, long long b) {
	if(!b) return a;
	gcd(b,a%b);
}

bool cmp(int i,int j) {
	return k[i] * b[j] < k[j] * b[i];
}

int main() {
	freopen("polyline.in","r",stdin);
	freopen("polyline.out","w",stdout);
	cin>>n;
	for(int i = 1; i <= n; i++) {
		long long ak,ab;
		cin>>ak>>ab;
		if(ak == 0) continue;
		k[++tot] = -ab;
		b[tot] = ak;
		vis[tot] = tot;
		if(b[tot] < 0) {
			k[tot] = -k[tot];
			b[tot] = -b[tot];
		}
		if(b[tot] == 0) {
			b[tot] = 1;
			continue;	
		}
		long long g = gcd(abs(k[tot]),abs(b[tot]));
		k[tot] /= g; b[tot] /= g;
	}
	sort(vis+1,vis+1+tot,cmp);
	ans = tot;
	for(int i = 1; i < tot; i++){
		if(k[vis[i]] == k[vis[i+1]] && b[vis[i]] == b[vis[i+1]]){
			ans--;
		}
	}
	cout<<ans;
	return 0;
}

##Problem 3. roadwork##
Input file: roadwork.in
Output file: roadwork.out
Time limit: 1s
Memory limit: 512M
现在有一条单个车道的路,两边会不断有车来,任意时刻路上只能有一个方向的车,每辆车速度相同,同一方向的车必须在前一辆车上路 3 秒后才能上路,可以在路口等待,不能超车,每个人在路口等过其忍受范围后便会不高兴,现在请你安排过路顺序,使得不高兴的人数最少。
Input
第一行两个整数t 和n,代表有n 辆车,每辆车过桥时间为t 秒
下⾯n ⾏,述每辆车,每行一个字符c,两个数字a 和r;
c=“E”或“W”代表方向,a 代表到达时间(秒),r 代表最多忍受时间(秒,上路时间- a),按到来顺序
给出,a 相同时以到来顺序为准。
Output
输出行一个整数,代表最少发怒人数。
Example
roadwork1.in
8 3
W 10 0
W 10 3
E 17 4
roadwork1.out
0
roadwork2.in
100 5
W 0 200
W 5 201
E 95 1111
E 95 1
E 95 11
roadwork2.out
1
Scoring
• 对于 100% 的数据,4 ≤t ≤180, 1 ≤n ≤250, 0 ≤a < 86400, 0 ≤r ≤3600

//dp渣表示完全不懂,现场暴力也没写出来
只能送上std

代码

// Solution of problem Road Work
// Time complexity: O(n^3)
// Space complexity: O(n^3)
// Author: Fredrik Svensson
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
using namespace std;

#define MAX_N 350
int resetValue = 123*MAX_N;
const int maxTotalTime = 86400+MAX_N*3+2*MAX_N*180;

struct Car
{
	int arrival;
	int lastLeave;
};
vector<Car> toWest;
vector<Car> toEast;
int timeToPass;

int dp[MAX_N+1][MAX_N+1][MAX_N+1][2]; // totalTime = dp[drivenEast][drivenWest][numIrritated][lastToWest=0,lastToEast=1]

int calc(int drivenWest, int drivenEast, int numIrritated, int lastToEast)
{
	int &dpv = dp[drivenWest][drivenEast][numIrritated][lastToEast];
	if (dpv == 0x7f7f7f7f)
	{
		if ((lastToEast ? drivenEast : drivenWest) == 0)
			dpv = maxTotalTime;
		else
		{
			const Car &myCar = (lastToEast ? toEast[drivenEast-1] : toWest[drivenWest-1]);
			if (lastToEast)
				--drivenEast;
			else
				--drivenWest;
			dpv = maxTotalTime;
			// Check with one less to the east and one less to the west.
			for (int dir = 0; dir < 2; ++dir)
			{
				// Allow getting irritated
				if (numIrritated > 0)
					dpv = min(dpv, calc(drivenWest, drivenEast, numIrritated-1, dir) + (dir == lastToEast ? 3 : timeToPass));
				// Not getting irritated
				int myTime = calc(drivenWest, drivenEast, numIrritated, dir) + (dir == lastToEast ? 3 : timeToPass);
				if (myTime <= myCar.lastLeave)
					dpv = min(dpv, myTime);
			}
			if (dpv < maxTotalTime)
				dpv = max(myCar.arrival, dpv);
		}
	}
	return dpv;
}

int main()
{
	freopen("roadwork.in","r",stdin);
	freopen("roadwork.out","w",stdout);
	int n;
	cin >> timeToPass >> n;
	for (int i = 0; i < n; ++i)
	{
		string d;
		int maxStillTime;
		Car car;
		cin >> d >> car.arrival >> maxStillTime;
		car.lastLeave = car.arrival + maxStillTime;
		if (d == "W")
			toWest.push_back(car);
		else if (d == "E")
			toEast.push_back(car);
		else
			return -1;
	}
	// Dynamic programming
	// Reset
	memset(&dp[0][0][0][0], 0x7f7f7f7f, sizeof(dp));
	dp[0][0][0][0] = dp[0][0][0][1] = -3;
	// Run
	int numIrritated;
	for (numIrritated = 0; numIrritated <= n; ++numIrritated)
	{
		int t = min(
			calc((int)toWest.size(), (int)toEast.size(), numIrritated, 0),
			calc((int)toWest.size(), (int)toEast.size(), numIrritated, 1));
		if (t < maxTotalTime)
			break;
	}
	cout << numIrritated << endl;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值