• Educational Codeforces Round 122 (Rated for Div. 2) ABCD


    A. Div. 7

    给一个数,问最少修改多少位可以让这个数被7整除。

    注意到7小于10,因此每10个数必然有一个7,所以最多只需要修改一次个位即可。

    #include <iostream>
    #include <cmath>
    #define ll long long
    using namespace std;
    int main() {
    	int t;
    	cin >> t;
    	while(t--) {
    		int n;
    		cin >> n;
    		if(n % 7 == 0) cout << n << endl;
    		else {
    			int a = n / 10 * 10;
    			for(int i = 0; i < 9; i++) {
    				if((a + i) % 7 == 0) {
    					cout << a + i << endl;
    					break;
    				}
    			}
    		}
    	}
    	return 0;
    }
    

    B. Minority

    给一个01字符串,可以选择一个子串,如果其中0的个数严格大于1的个数则将1删掉,如果1的个数严格大于0的个数则将0删掉,问最多能删掉多少数。

    首先如果整个串中0和1个数不一样,那么直接选整个串即可;如果一样的话,则选除这个串第一个字符外剩下所有字符构成的子串,这样显然答案最大。

    #include <iostream>
    #include <cmath>
    #define ll long long
    using namespace std;
    int main() {
    	int t;
    	cin >> t;
    	while(t--) {
    		string s;
    		cin >> s;
    		int zero = 0, one = 0;
    		for(int i = 0; i < s.size(); i++) {
    			if(s[i] == '0') zero++;
    			else one++;
    		}
    		if(zero == one) cout << zero - 1 << endl;
    		else cout << min(zero, one) << endl;
    	}
    	return 0;
    }
    

    C. Kill the Monster

    最关键的是要注意到k的范围总共才2e5,自然想到枚举k然后判断能否击败。几百的条件是character攻击的次数小于等于怪物攻击的次数。

    #include <iostream>
    #include <cmath>
    #define ll long long
    using namespace std;
    ll hc, dc, hm, dm, k, w, a;
    bool check() {
    	ll num1 = ceil(1.0 * hm / dc);
    	ll num2 = ceil(1.0 * hc / dm);
    	return num1 <= num2;
    }
    int main() {
    	int t;
    	cin >> t;
    	while(t--) {
    		cin >> hc >> dc;
    		cin >> hm >> dm;
    		cin >> k >> w >> a;
    		//注意k的和不超过2e5
    		bool ok = 0;
    		for(ll i = 0; i <= k; i++) {//有i个加hc
    			hc += i * a;
    			dc += (k - i) * w;
    			if(check()) {
    				ok = 1;
    				break;
    			}
    			hc -= i * a;
    			dc -= (k - i) * w;
    		}
    		if(ok) puts("YES");
    		else puts("NO");
    	}
    }
    

    D. Make Them Equal

    首先注意到,因为每个ai起始都为1,因此ai到达bi的次数是固定的。可以预处理出1到1000范围内从1变换到每个数的次数,然后实际上这个问题就变成了一个最简单的01背包模型。预处理的话我一开始想到的是倍增/枚举因子贪心,然而实际上这样得到的不一定是最优解。一个正确的做法是求一遍最短路,起点为1,a到b路径长度是从a变换到b的次数。还有一点需要注意,输入说明中显示k范围1e6,如果dp数组第二维直接开1e6必然TLE/MLE。而b的范围是1000,按照纯倍增做法,一个数至多变换2log1000次,如果再枚举因子贪心的话变换次数还会降低,实测每个数变换次数上界为13,因此若干k大于n * 13则直接取k = n * 13即可。

    #include <iostream>
    #include <vector>
    #include <queue>
    #include <cstring>
    using namespace std;
    int n, k, dp[13005], a[1005], b[1005], c[1005], num[1005], f[1005], v[1005];
    void dijkstra() {
    	memset(v, 0, sizeof(v));
    	memset(f, 0x3f, sizeof(f));
    	priority_queue<pair<int, int> > q;
    	f[1] = 0;
    	q.push(make_pair(0, 1));
    	while(q.size()) {
    		int now = q.top().second;
    		q.pop();
    		if(v[now]) continue;
    		v[now] = 1;
    		for(int i = 1; i <= now; i++) {
    			int nxt = now + now / i;
    			if(nxt <= 1000 && f[nxt] > f[now] + 1) {
    				f[nxt] = f[now] + 1;
    				q.push(make_pair(-f[nxt], nxt));
    			}
    		}
    	}
    
    }
    int main() {
    	int t;
    	cin >> t;
    	
    	dijkstra();
    	while(t--) {
    		cin >> n >> k;
    		for(int i = 0; i <= 13000; i++) dp[i] = 0;
    		for(int i = 1; i <= n; i++) {
    			cin >> b[i];
    			a[i] = 1;
    			num[i] = 0;
    		}
    		for(int i = 1; i <= n; i++) {
    			cin >> c[i];
    		}
    		for(int i = 1; i <= n; i++) {
    			num[i] = f[b[i]];
    		}
    		int ans = 0;
    
    		for(int i = 1; i <= n; i++) {
    			for(int j = min(k, 13 * n); j - num[i] >= 0; j--) {
    				dp[j] = max(dp[j], dp[j - num[i]] + c[i]);
    				ans = max(ans, dp[j]);
    			}
    		}
    		cout << ans << endl;
    	} 
    	return 0;
    }
    // 7 12
    // 11 57 71 26 31 99 58
    // 62 66 82 31 94 18 74
    
  • 相关阅读:
    CSPS模拟 49
    StrGame
    CSPS模拟 48
    [没有证明]原根求法
    CSPS模拟 47
    CSPS模拟 46
    CSPS模拟 45 乔迁之喜
    CSPS模拟 44
    平衡二叉树
    go语言学习--指针数组和数组指针
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15859312.html
Copyright © 2020-2023  润新知