• Codeforces Round #658 (Div. 2)


    A.Common Subsequence

    题意

    给你两组数,问你有没有相同 的书,有的话,输出最短的那组(大家都知道,1是最小的)

    AC

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1005;
    int a[N], x, n, m, flag, t;
    int main() {
    	//freopen("in.txt","r",stdin);
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	cin >> t; while (t--) {
    		cin >> n >> m;
    		for (int i = 0; i < n; ++i)cin >> x, a[x]++;
    		flag = 0;
    		for (int i = 0; i < m; ++i) {
    			cin >> x;
    			if (a[x])
    				flag = x;
    		}
    		if (flag) {
    			cout << "YES" << endl;
    			cout << 1 << " " << flag << endl;
    		}
    		else cout << "NO" << endl;
    	}
    }
    

    B.Sequential Nim

    题意:

    两个人玩区石子游戏,有n堆,第i堆有a[i]个,每个人只能按堆的顺序拿,就是前面这堆没有拿完,不能拿下一堆。谁先不能拿就输了。

    思路:

    谁先遇到大于1的石子堆,谁就一定不会输,因为大于1的石子堆,我可以选择全拿完和留一个,这两种状态结果是互斥的,必定会有一个状态的必胜态,所以只要判断到大于1的数前面的1的数量就行,若是全1的情况,那就轮流拿,单独判断一下就行。

    #include<bits/stdc++.h>
    using namespace std;
    int main() {
        int n, t, x, flag, cnt;
        //freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin >> t; while (t--) {
            cin >> n; cnt = 0; flag = 0;
            while (n--) {
                cin >> x;
                if (x == 1 && flag == 0)
                    cnt++;
                if (x > 1)
                    flag = 1;
            }
            if ((cnt % 2 == 1 && flag) || (cnt % 2 == 0 && flag == 0))
                cout << "Second" << endl;
            else
                cout << "First" << endl;
        }
    }
    

    C1Prefix Flip (Easy Version)

    题意;

    给你两个长度相同的01字符串a,b,有一种操作,我们可以把一个字符串长度为x的前缀拿出来,把0,1互换,(就像是异或一下)然后再把这个前缀翻转(掉个头)放回到原字符串中,问我们通过几次这种操作把a转换为b。操作数小于2*n;

    思路:

    因为我们每次拿的都是前缀,那么也就是说,后面的不会动了,那么我们可以从后往前来,遇到不同的,就判断a开头位置和b当前位置(因为不同就要进行”异或“然后翻转,会把第一个数翻转到当前位置上,所以判断a第一个位置和b当前位置)
    如果第一位置和当前位置相同,要把第一位置单独转一下,(因为相同,异或再转过来就不同了)记录一下每次翻转的位置就是答案。

    #include<bits/stdc++.h>
    using namespace std;
    int main() {
    	//freopen("in.txt","r",stdin);
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	string a, b; int t; cin >> t;
    	while (t--) {
    		int n; cin >> n;
    		cin >> a >> b; int ans = 0;	
    		for (int i = 0; i < n; ++i)if (a[i] != b[i])ans++;
    		cout << 3 * ans << " ";
    		for (int i = 0; i < n; ++i)if (a[i] != b[i])cout << i + 1 << " 1 " << i + 1 << " ";
    		cout << endl;
    	}
    }
    

    C2题待补

    D. Unmerge(01背包问题,1800)

    题意:

    对于两个数组,定义merge运算:每次把两个数组的首部的较小的那个拿出,并放到一个新的数组中。现在给定一个长度为n*2的排列,问你这个排列是否可能由两个长度为n的数组merge得到?可能则打印yes,否则no。

    思路:

    因为每次拿头部最小的放进新数组,所以一旦我们碰到一个数值a[i],紧跟a[i]后面的并且小于a[i]的全都应该和a[i]是同一组的,那么我们对于每次出现的这种,我们记录它们的长度。如果可能由两个长度为n的组成,那么我们可以找到一些长度,他们加起来等于n,也就是01背包问题了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 4e3 + 10;
    int dp[N], d[N], a[N];
    int main() {
    	//freopen("in.txt","r",stdin);
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	int t, n; cin >> t; while (t--) {
    		cin >> n;
    		memset(dp, 0, sizeof dp);
    		for (int i = 1; i <= 2 * n; ++i)cin >> a[i];
    		int mx = a[1], cnt = 1, len = 0;
    		for (int i = 2; i <= 2 * n; ++i) {
    			if (a[i] > mx) {
    				mx = a[i];
    				d[++len] = cnt;
    				cnt = 1;
    			}
    			else
    				cnt++;
    		}
    		d[++len] = cnt;
    		for (int i = 1; i <= len; i++)
    			for (int j = n; j >= d[i]; j--)
    				dp[j] = max(dp[j], dp[j - d[i]] + d[i]);
    		if (dp[n] == n) cout << "YES" << endl;
    		else cout << "NO" << endl;
    	}
    }
    

    E题待补

  • 相关阅读:
    http
    node 学习 http
    socket.io
    每日日报
    每日日报
    每日日报
    06人件读书笔记之一
    每日日报
    每日日报
    05程序员修炼之道:从小工到专家阅读笔记之三
  • 原文地址:https://www.cnblogs.com/RioTian/p/13372223.html
Copyright © 2020-2023  润新知