AtCoder Beginner Contest 234 (A,B,C,D,E,F)

A - Weird Function

计算规定的函数值即可

ACcode

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll f(ll x){
	ll res = x * x + 2 * x + 3;
	return res;
}

int main(){
	
	ll t;
	cin >> t;
	ll res = f(f(f(t)+t)+f(f(t)));
	cout << res << endl;
	
	return 0;
}

B - Longest Segment

N 个点中,选两个点构成最长的线段。 O ( N 2 ) O(N^2) O(N2) 暴力计算即可。

ACcode

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn = 3e6 + 5;

double a[1005], b[1005];

double dis(int i, int j){
	double len = (a[i] - a[j]) * (a[i] - a[j]);
	len += (b[i] - b[j]) * (b[i] - b[j]);
	return len;
}

int main(){
	
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i] >> b[i];
	
	double res = 0;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			double tmp = dis(i, j);
			if(tmp > res) res = tmp;
		}
	}
	
	printf("%.10lf\n", sqrt(res));
	
	return 0;
}

C - Happy New Year!

本质就是计算 k 的二进制表示,注意把 ’1‘ 变成 ’2‘

ACcode

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int main(){
	
	ll k;
	cin >> k;
	
	string res = "";

	while(k){
		if(k&1) res = "2" + res;
		else res = "0" + res;
		k >>= 1;
	}	
	
	cout << res << endl;
	
	return 0;
}

D - Prefix K-th Max

依次输出序列前 i i i ( k < = i < = n ) (k <= i <= n) (k<=i<=n)的第 k k k 大。
用树状数组统计那个数字出现过,二分找第 k 大出现的数字。
ps:维护方法很多只要把前 k 大保留下来即可。

#include<bits/stdc++.h>
#include<queue>
#define ll long long
using namespace std;

const int maxn = 3e6 + 5;

int lowbit(int A){
	return A & (-A);
}

int a[maxn];
int t[maxn];
void add(int A){
	while(A < maxn){
		t[A]++;
		A += lowbit(A);
	}
}

int query(int A){
	int res = 0;
	while(A > 0){
		res += t[A];
		A -= lowbit(A);
	}
	return res;
}

int main(){
	
	int n, k;
	cin >> n >> k;
	for(int i = 1; i <= n; i++) cin >> a[i];
	
	for(int i = 1; i < k; i++) add(a[i]);
	for(int i = k; i <= n; i++){
		add(a[i]);
		int pos = i - k + 1;
		int l = 1, r = n, res = -1;
		while(l <= r){
			int mid = l + r >> 1;
			if(query(mid) >= pos){
				res = mid;
				r = mid - 1;
			}
			else l = mid + 1;
		}
		cout << res << endl;
	}
	
	return 0;
}

E - Arithmetic Number

找到第一个大于等于 X 且满足要求的数字(每个数位等差)。
枚举第一位数是什么和公差是多少即可。时间复杂度: O ( 9 ∗ 19 ∗ 17 ) O(9 * 19 * 17) O(91917)

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn = 3e6 + 5;

ll a[1005];
ll b[1005];

ll len, num = 0, res = 1e18;
void dfs(ll d, ll ai, ll now, ll step){
	if(step == len){
		if(now >= num && now < res) res = now; 
		return;
	}
	ll tmp = ai + d;
	if(tmp < 0 || tmp > 9) return;
	now = now * 10 + tmp;
	dfs(d, tmp, now, step+1);
}

int main(){
	
	string s;
	cin >> s;
	
	len = s.size();
	for(int i = 0; i < len; i++) a[i] = s[i] - '0';
	for(int i = 0; i < len; i++) num = num * 10 + a[i];
	
	for(int i = 1; i <= 9; i++){
		for(int j = -9; j <= 9; j++){
			dfs(j, i, i, 1);
		}
	}
	
	cout << res << endl;
		
	
	return 0;
}

F - Reordering

计算字符串 S 的全部非空子序列的全排列组成的字符串的种类。
定义: d p i , j dp_{i,j} dpi,j 表示前 i 个字符构成长度为 j 的字符串的种类数
转移方程为: d p i , j = d p i − 1 , j − k ∗ C ( j , k ) , i < = 26 , k < = 第 i 种 字 符 出 现 的 次 数 dp_{i,j} = dp_{i-1,j-k} * C(j, k), i <= 26, k <= 第i种字符出现的次数 dpi,j=dpi1,jkC(j,k),i<=26,k<=i

#include<bits/stdc++.h>
#include<queue>
#define ll long long
using namespace std;

const int maxn = 5000 + 5;
const ll mod = 998244353;

ll f[maxn], inv[maxn];
ll dp[27][maxn];
int v[27];

ll qpow(ll a, ll b){
	ll res = 1;
	while(b){
		if(b&1) res *= a;
		res %= mod;
		a *= a;
		a %= mod;
		b >>= 1;
	}
	return res;
}

ll C(ll n, ll m){
	return f[n] * inv[m] % mod * inv[n-m] % mod;
}

int main(){
	
	f[0] = inv[0] = 1;
	for(int i = 1; i <= 5000; i++) f[i] = f[i-1] * i % mod;
	for(int i = 1; i <= 5000; i++) inv[i] = qpow(f[i], mod-2);
	
	string s;
	cin >> s;	
	
	int len = s.size();
	for(int i = 0; i < len; i++) v[s[i]-'a'+1]++;
	dp[0][0] = 1;
	for(int i = 1; i <= 26; i++){
		for(int j = 0; j <= len; j++){
			for(int k = 0; k <= min(j, v[i]); k++){
				dp[i][j] += dp[i-1][j-k] * C(j, k) % mod;
				dp[i][j] %= mod;
			}
		}
	}
	
	ll ans = 0;
	for(int i = 1; i <= len; i++) ans += dp[26][i], ans %= mod;
	cout << ans << endl;	
		
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值