SMU Autumn 2023 Round 2(Div.1+2)

发布时间 2023-09-10 23:57:12作者: Ke_scholar

SMU Autumn 2023 Round 2(Div.1+2)

C. Chaotic Construction

把环展开的话就是\(1 \sim 2n\),若\(D\)的位置放上路障的话,在这个展开的环上就是\(D\)\(D+n\)的位置,对于\(x,y\),我们就是去看\(D\)或者\(D+n\)是否处于\(x,y\)中间的位置,可以设置一个\(ans = 0\)表示最开始无路障时都能走通,然后对存进\(set\)里的路障二分找到\(x,y\)\(y,x+n\)中间是否存在路标,若存在,则\(ans+1\),当\(ans = 2\)时说明无论向前还是向后都走不通

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, q;
	map<int, int> f;
	cin >> n >> q;

	set<i64> road;
	road.insert(0);
	for (int i = 0; i < q; i ++) {
		char op;
		int x, y;
		cin >> op >> x;
		if (op == '?') {
			cin >> y;
			if (x > y) swap(x, y);
			if (f[x] || f[y]) {
				cout << "impossible\n";
				continue;
			}

			int ans = 0;
			auto p = *road.lower_bound(x),q = *road.lower_bound(y);
			if(p != q) ans ++ ;
			auto pq = *road.lower_bound(x + n);
			if(pq != q) ans ++;
			cout << (ans > 1 ? "impossible\n" : "possible\n");

		} else {
			if (op == '-') {
				f[x] = 1;
				road.insert(x), road.insert(x + n);
			}
			else {
				f[x] = 0;
				road.erase(x), road.erase(x + n);
			}
		}
	}

	return 0;
}

D. Diabolic Doofenshmirtz

\(1e12\)不会超过\(2^{42}\),所以询问的时候可以倍增地去问,每次记录上一次回答的长度,如果当某次的\(x\)小于了之前记录的长度,说明这个时候刚好已经跑过一圈了,而这个时候的\(x\)是跑了一圈之后的位置,\(now\)是现在跑了的路程,那么\(now - x\)即为一圈的长度了

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    i64 now = 1, last = 0;
    for(int i = 1;i <= 42;i ++){
        cout << "? " << now << endl;
        i64 x;
        cin >> x;
        if(x <= last){
            cout << "! " << now - x << endl;
            break;
        }
        last = x;
        now *= 2;
    }

    return 0;
}

E. Enjoyable Entree

规律题,如果你打表的话就会发现当\(n\)超过\(30\)之后,两个比例都会趋近一个极限\(33.333333\)\(66.666667\),想到了这点就容易做了

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    i64 n;
    cin >> n;
    if(n == 1){
        cout << "100 0\n";
    }else if(n == 2){
        cout << "0 100\n";
    }else{
        if(n > 30){
            cout << "33.333333 66.666667\n";
        }else{
            double ans = 50, a = 50,b = 25;
            for(int i = 5;i <= n;i ++){
                ans = a / 2 + b / 2;
                a = b;
                b = ans;
            }
            if(n == 3)
                cout << "50 50\n";
            else if(n == 4)
                cout << "25 75\n";
            else
                printf("%.6lf %.6lf\n",ans, 100 - ans);
        }
    }

    return 0;
}

I. Improving IT

\(f[i]\)表示第\(i\)个月赚了多少钱,首先最开始\(dp[i]=0\)表示没有买\(CPU\)时的初值,此后每个月都减掉\(a\)表示新买一个\(CPU\)所花掉的钱,\(dp[i+j]=max(dp[i+j],dp[i]+b)\)则代表第\(i+j\)个月以\(b\)价格卖出第\(i\)月买的\(CPU\)是否会赚的更多

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n,m;
    cin >> n >> m;
    vector<i64> f(n + 2,-LLONG_MAX);    
    f[1] = 0;
    for(int i = 1;i <= n;i ++){
        int a;
        cin >> a;
        f[i] -= a;
        for(int j = 1;j <= min(m, n - i + 1);j ++){
            int b;
            cin >> b;
            f[i + j] = max(f[i + j], f[i] + b);
        }
    }

    cout << -f[n + 1] << '\n';

    return 0;
}

K. K.O. Kids

\(f=1\)时应该迈左脚,\(f=0\)时迈右脚,否则的话就丢掉一个人,正常模拟即可

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n,k;
	string s;
	cin >> n >> k >> s;

	bool f = 1;
	int ans = k;
	for(int i = 0;i < n;i ++){
		if(f && s[i] != 'L')
			ans --;
		else if(!f && s[i] != 'R')
			ans --;
		else f ^= 1;
	}

	cout << max(0, ans) << '\n';

	return 0;
}

L. Lots of Land

当整个矩形的面积不能整除\(n\)时说明不能划分成\(n\)个面积相等的矩形,,否则的话就取\(k = \frac{S}{n}\),则每个小矩形的面积就等于\(k\),则让\(k\)与边或宽取个最大公约数就能计算出小矩形的长和宽,然后就是正常模拟

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int l,w,n;
	cin >> l >> w >> n;
	vector<string> g(l, string(w, 'A'));
	if((l * w) % n != 0){		
		cout << "IMPOSSIBLE\n" ;
	}else{
		int k = l * w / n;
		char op = 'A';
		int L = gcd(k, l), W = k / L;
		for(int i = 0;i < l;i ++){
			int p = 0;
			for(int j = 0;j < w;j ++){
				if(j && j % W == 0) p++;
				g[i][j] = op + p;
			}
			if((i + 1) % L == 0) op = op + p + 1;
		}

		for(auto i : g)
			cout << i << '\n';
	}

	return 0;
}