Codeforces Round #678 Div. 2

A. Reorder

给定一串数列和m,问是否可能存在一个重排令

\[\sum_{i=1}^{n}\sum_{j=i}^{n}(double)a_{j}/j==m \]

直接和是否等于m

#include<iostream>
#include<queue>
#include<map>
#include<utility>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<cmath>
#include<set>
#include<math.h>
using namespace std;
typedef  long long  ll;					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
typedef pair<int, int> P;
ll m;
int main() {
	cin >> m;
	while (m--)
	{
		ll a, b;
		cin >> a >> b;
		ll ans = 0;
		for (int i = 0; i < a; i++) {
			ll tmp;
			cin >> tmp;
			ans += tmp;
		}
		if (ans == b)cout << "YES\n";
		else cout << "NO\n";
	}
}

B .Prime Square

给定n,求一个n×n的矩阵,令矩阵中每个数字都不是质数,每行每列和是质数

0,1不是质数,2,3是质数

只要把1按X状排列,然后再把第一列的中间那个数改成1即可

#include<iostream>
#include<queue>
#include<map>
#include<utility>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<cmath>
#include<set>
#include<math.h>
using namespace std;
typedef  long long  ll;					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
typedef pair<int, int> P;
ll m;
int main() {
	cin >> m;
	while (m--)
	{
		ll a, b;
		cin >> a;
		ll ans = 0;
		for (int i = 0; i < a; i++) {
			for (int j = 0; j < a; j++) {
				if (i == j||i+j==a-1||(j==0&&i==a/2)|| (i == 0 && j == a / 2))cout << 1 << ' ';
				else cout << 0 << ' ';
			}
			cout << '\n';
		}
	}
}

给定一串长度为n的数列,问有多少种排列能用二分法找到pos处的X

我们模拟二分操作,就能知道要找出X的话,

在什么位置需要放大于X的数,什么地方放小于X的数,然后求组合数即可

#include<iostream>
#include<queue>
#include<map>
#include<utility>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<cmath>
#include<set>
#include<math.h>
using namespace std;
typedef  long long  ll;					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
typedef pair<int, int> P;
ll n, x, pos;
ll lm = 0, rm = 0;
const ll mod = 1e9 + 7;
ll inv[10000];
ll f[10000];
ll qpow(ll a, ll b) {
	ll res = 1;
	a %= mod;
	while (b)
	{
		if (b & 1)res = (res * a) % mod;
		b >>= 1;
		a = a * a % mod;
	}
	return res;
}
void pre(ll len) {
	f[0] = 1;
	for (int i = 1; i <= len; i++)
		f[i] = i * f[i - 1] % mod;
	inv[len] = qpow(f[len], mod - 2);
	for (int i = len - 1; i >= 0; i--)inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll A(ll n, ll m) {
 
	if (n < m || n < 0)return 0;
	return f[n] % mod * inv[n - m] % mod;
}
int main() {
	cin >> n >> x >> pos;
	ll l = 0, r = n, mid = -1;
	pre(1000 + 5);
	ll ans = 1;
	while (1)
	{
		mid = (l + r) / 2;
		if (mid == pos) {
			l = mid + 1; break;
		}
		else if (mid > pos) lm++, r = mid;
		else rm++, l = mid + 1;
	}
	while (l<r)
	{
		r = (l + r) / 2;
		lm++;
	}
	ans = A(n - x, lm) * A(x - 1, rm) % mod * A(n - lm - rm - 1, n - lm - rm - 1) % mod;
		
	cout << ans;
}

D. Bandit in a City

给定一个树和每个点的人数,某时刻根出现强盗,每次行动强盗和所有人都要选其中一个子树走,

最终强盗所在的叶子的人数最小值是多少 强盗和人都倾向于最优解

考虑强盗到达某一节点,如果强盗下到其中一个子节点,其他人就应该都跑到其他节点为最优状况,

所以强盗抓到人数的最好情况是以当前节点为根的子树的和/当前子树的叶子数,

但是不一定能够均匀分配,所以求所有的sum[u]/lev[u]的最值

#include<iostream>
#include<queue>
#include<map>
#include<utility>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<cmath>
#include<set>
#include<math.h>
using namespace std;
typedef  long long  ll;					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
typedef pair<int, int> P;
ll n, m, pos;
ll lm = 0, rm = 0;
const ll mod = 998244353;
ll dat[300000+5];
vector<ll>s[300000 + 5];
const int maxn = 100005;
ll son[300000 + 5];
ll val[300000 + 5];
ll dfs(ll x) {
    if (s[x].size() == 0||val[x])return val[x]=dat[x];
    ll ans = dat[x];
    for (int i = 0; i < s[x].size(); i++) {
        ans += dfs(s[x][i]);
    }
    return val[x] = ans;
}
ll dfs2(ll x) {
    if (s[x].size() == 0 || son[x] != 0)return son[x]=1;
    ll ans = son[x];
    for (int i = 0; i < s[x].size(); i++) {
        ans += dfs2(s[x][i]);
    }
    return son[x] = ans;
}
ll cal(ll x) {
    ll ans = -1;
    for (int i = 1; i <= n; i++) {
        ans = max(ans,(val[i]+son[i]-1) / son[i]);
   }
    return ans;
}
int main() {
    cin >> n;
    for (int i = 2; i <= n; i++) {
        ll tmp;
        cin >> tmp;
        s[tmp].push_back(i);
    }
    for (int i = 1; i <= n; i++)cin >> dat[i];
    dfs(1);
    dfs2(1);
    ll ans = cal(1);
    cout << ans;
}
 

E. Complicated Computations

规定数列的MEX为数列中第一个没有出现的数,求给定数列MEX的MEX

由给定的每个数都小于等于n,想到从1到n枚举,看是否可以是MEX,最后求总的MEX

考虑数字a,如果在两个a的间隔(或者开头到第一个a,最后一个a到结尾)中1到a-1都出现了,那么a就可以当作MEX,

按顺序更新,

令上次a出现的位置为lst[a],当前a的位置是i,只要求1到a-1出现的位置的最小值都大于lst[a]那么他们就都出现了,

a就可以作为MEX的值,后更新lst[a]即可

1要特判

#include<iostream>
#include<queue>
#include<map>
#include<utility>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<cmath>
#include<set>
#include<math.h>
using namespace std;
typedef  long long  ll;					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ll vis[100000 + 5];
ll dat[100000 + 5];
ll val[100001 << 2];
ll lst[100000 + 5];
ll n;
void updata(ll o, ll l, ll r, ll pos, ll n) {
    if (l == r)return (void)(val[o] = n);
    ll mid = (l + r) / 2;
    if (mid >= pos)updata(o << 1, l, mid, pos, n);
    else updata(o << 1 | 1, mid + 1, r, pos, n);
    val[o] = min(val[o << 1], val[o << 1 | 1]);
}
ll q(ll o, ll l, ll r, ll L, ll R) {
    if (l >= L && r <= R) {
        return val[o];
    }
    else {
        ll ans = 1000000;
        ll mid = l + (r - l)/2;
        if (L <= mid)ans=min(ans,q(o << 1, l,mid, L, R));
        if (R > mid)ans = min(ans, q(o << 1 | 1, mid + 1, r, L, R));
        return ans;
    }
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)cin >> dat[i];
    for (int i = 1; i <= n; i++) {
        if (dat[i] > 1)vis[1] = 1;
        if(dat[i]>1)q(1, 1, n, 1, dat[i] - 1);
        if (dat[i] > 1 && q(1, 1, n, 1, dat[i] - 1) > lst[dat[i]])vis[dat[i]] = 1;
        lst[dat[i]] = i;
        updata(1, 1, n, dat[i], i);
    }
    for (int i = 2; i <= n + 1; i++)
        if (q(1, 1, n, 1, i - 1) > lst[i])vis[i] = 1;
    ll ans = 1;
    while (vis[ans])ans++;
    cout << ans;
    
}

posted @ 2020-11-21 00:16  PopHirasawa  阅读(91)  评论(0编辑  收藏  举报