2019summer系列 周末划水

https://vjudge.net/contest/310810#overview

A


我们可以用 0…359 之间的角度来描述一个方向,现在给出两个方向 a , b,你需要求出,从 a 转到 b 最少需要的角度。
例如,从 70° 转到 180°,可以转 110°,也可以转 -250°
又比如,从315°转到45°,可以转90°,也可以转 -270°
定义一个角度 a 比另一个角度 b 小,当且仅当 a 的绝对值小于 b。
例如:180°比 -220°小,-45°比80°小。
特别的,如果两个角度的绝对值相同,我们规定正的角度比较小,比如180°小于-180°
Input
第一行两个 0 到 359之间的整数 a , b
Output
输出最少需要转的角度
Sample Input
315 45
Sample Output
90

我也不知道怎么解释,当心正负吧。

#include<bits/stdc++.h>
using namespace std;
int a,b,m,n;
int main(){
	cin >> a>> b;
	if(a>b) b += 360;
	m = (b-a)%360;
	n = -((360-b+a)%360);
	if(abs(m)<abs(n)) cout <<m;
	else if(abs(n)<abs(m)) cout << n;
	else cout<<abs(m);
    return 0;
}

B


小 Hi 有一个正整数 n,但他忘了这个数是啥了。他只记得 n 的所有约数的平均数是 a,n 的所有约数的调和平均数是 h ,且 a 和 h 都是正整数,现在小 Hi 想要你找出 n 的值。保证 n 存在,且小于等于 108
注:
n个数a1,a2…an的算术平均数为∑ai / n
n个数a1,a2…an的调和平均数为n / ∑(1/ai)
Input
第一行两个正整数 a , h
Output
输出一个正整数
Sample Input
3 2
Sample Output
6

猜测输出a*h就好了,嗯!猜测成功!

C


小 Hi 手上有 n 张面值互不相同的钱币,且面值都是 2 的幂次,现在他想知道,他可以组合出多少种小于等于 c 的正整数金额。
Input
第一行两个正整数 n , c (1 ≤ n ≤ 50, 1 ≤ c ≤ 1018)
第二行n个互不相同的正整数,表示小Hi手上钱币的面值,保证面值都是 2 的幂次,且不超过 1018
Output
输出一个整数表示答案
Sample Input
3 10
4 1 8
Sample Output
5
Hint
可以拼出 1, 4, 5, 8, 9

先全部转化成二进制,然后dp;
d p [ i ] dp[i] dp[i] 表示在最高位为 i 的时候,不大于 c 的金额的种类。
先预处理出来一个 sum 数组,表示在最高位为 i 的时候,用现有的钱可以组合出多少种金额。
于是,若 c 的二进制从低位开始的第 i 位为1,若此时有这种金额的货币,那么 d p [ i ] = d p [ i − 1 ] + s u m [ i − 1 ] dp[i] = dp[i-1] + sum[i-1] dp[i]=dp[i1]+sum[i1],如果没有这种金额的货币, d p [ i ] = s u m [ i − 1 ] dp[i] = sum[i-1] dp[i]=sum[i1];若为0, d p [ i ] = d p [ i − 1 ] dp[i] = dp[i-1] dp[i]=dp[i1]

#include<bits/stdc++.h>
using namespace std;
set<long long int> st;
bool is[80];
bool big[80];
typedef long long int ll;
long long int f[80],sum[80];
long long int n,c,a,M=1;
int main(){
	cin >> n>> c;
	memset(is,false,sizeof is);
	memset(f,0,sizeof f);
	for(int i = 0;i < n;i ++){
		cin >> a;
		st.insert(a);
	}
	for(int i = 0;i<=70;i++){
		if(st.count(M)==1) is[i] = true;
		M <<= 1ll;
	}
	int fi = 0;
	while(c){
	   if(c&1) big[fi]=true;
	   else big[fi]=false;
	   fi++;
       c>>=1ll;
	}
    fi--;
	if(is[0]) sum[0] = 2ll;
	else sum[0] = 1ll;
	for(int i = 1;i <= 70;i ++){
		if(is[i]) sum[i] = sum[i-1]*2ll;
		else sum[i] = sum[i-1];
	}
	
	if(is[0]&&big[0]) f[0] = 2ll;
	else f[0] = 1ll;
	
	for(int i=1;i<=70;i++){
		if(big[i]&&is[i])	f[i]=f[i-1]+sum[i-1];
		else if(big[i])	f[i]=sum[i-1];
		else f[i]=f[i-1];
	}
	cout << f[70]-1ll;
    return 0;
}

D


你有 n 个数位( 1 到 9 ),现在你需要用他们组成 k 个正整数,使得最大的数最小
Input
第一行两个正整数 n , k (1 ≤ k ≤ n ≤ 105)
第二行一个长度为 n 的数字串,表示你拥有的数位。
Output
出最大的数的最小值
Sample Input
7 4
4412377
Sample Output
34
Hint
组成:17, 34, 27, 4

// copy from zzy 
#include <bits/stdc++.h>
using namespace std;
int n,k;
string s;
int num[10];
int main(){
	cin>>n>>k;
	cin>>s;
	for (int i=0;i<n;i++)
		num[(int)s[i]-(int)'0']++;
	int l = n/k+1, m = n%k;//l是长串的长度,m是长串的个数
	if (n%k == 0) { //所有串长度一样 
		m += k; l --;
	}
	for (int i = 1; i <= l; i ++){
		int j=0;
		while (j<=9){
			if (num[j]>=m){ //每个长串都填一个 
				cout<<j;
				num[j]-=m;
				break;
			} else { //有些串已经不再可能是最大的串了 
				m-=num[j];
				num[j]=0;
			}
			j++; 
		}
	}
	return 0;	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值