zoukankan      html  css  js  c++  java
  • Codeforces Round #724 (Div. 2) 题解

    比赛地址

    A. Omkar and Bad Story

    题面

    首先不难发现最后 (b) 数组中没有负数,因为最大的数减去一个负数后会得到一个更大的数,显然不满足题目条件。

    如果 (a) 数组中有负数,则直接输出 NO,否则由于值域很小,输出 (0sim 100) 即可。

    代码:

    // Problem: A. Omkar and Bad Story
    // Contest: Codeforces - Codeforces Round #724 (Div. 2)
    // URL: https://codeforces.ml/contest/1536/problem/A
    // Memory Limit: 256 MB
    // Time Limit: 2000 ms
    // Author: csxsl
    // Created: 2021-06-27 21:31:36
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    #define DC int T = gi <int> (); while (T--)
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
        T f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 303, M = N << 1;
    
    int n, a[N];
    
    int main()
    {
        //File("");
        DC
        {
        	n = gi <int> ();
        	for (int i = 1; i <= n; i+=1) a[i] = gi <int> ();
        	if (*min_element(a + 1, a + 1 + n) < 0) puts("NO");
        	else 
        	{
        		puts("YES
    101");
        		for (int i = 0; i <= 100; i+=1) printf("%d ", i);
        		puts("");
        	}
        }
        return 0;
    }
    

    B. Prinzessin der Verurteilung

    题面

    一个小性质:长度为 (n) 的字符串中最多有不同的长度为 (k) 的字串 (n-k+1) 个。

    那么由于 (26^2<1000<26^3),因此直接按字典序从小到大枚举每一个长度 (le 3) 的字符串,判断它是不是这个字符串的一个子串即可。

    代码:

    // Problem: B. Prinzessin der Verurteilung
    // Contest: Codeforces - Codeforces Round #724 (Div. 2)
    // URL: https://codeforces.ml/contest/1536/problem/B
    // Memory Limit: 256 MB
    // Time Limit: 2000 ms
    // Author: csxsl
    // Created: 2021-06-27 21:40:51
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    #define DC int T = gi <int> (); while (T--)
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
        T f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 100003, M = N << 1;
    
    int n;
    char s[N];
    
    int main()
    {
        //File("");
        DC
        {
        	n = gi <int> (); scanf("%s", s + 1);
        	bool fl = false;
        	for (char i = 'a'; i <= 'z' && !fl; i+=1)
        	{
        		bool have = false;
        		for (int j = 1; j <= n; j+=1)
        			if (s[j] == i) have = true;
        		if (!have) {printf("%c
    ", i); fl = true; break;}
        	}
        	if (fl) continue;
        	for (char i = 'a'; i <= 'z' && !fl; i+=1)
        		for (char j = 'a'; j <= 'z' && !fl; j+=1)
        		{
        			bool have = false;
        			for (int k = 1; k < n; k+=1)
        				if (s[k] == i && s[k + 1] == j) have = true;
        			if (!have) {printf("%c%c
    ", i, j), fl = true; break;}
        		}	
        	if (fl) continue;
        	for (char i = 'a'; i <= 'z' && !fl; i+=1)
        		for (char j = 'a'; j <= 'z' && !fl; j+=1)
    	    		for (char l = 'a'; l <= 'z' && !fl; l+=1)
    	    		{
    	    			bool have = false;
    	    			for (int k = 1; k < n - 1; k+=1)
    	    				if (s[k] == i && s[k + 1] == j && s[k + 2] == l) have = true;
    	    			if (!have) {printf("%c%c%c
    ", i, j, l), fl = true; break;}
    	    		}	
        }
        return 0;
    }
    

    C. Diluc and Kaeya

    题面

    不难发现每个子串的 (n(D):n(K)) 就等于整个字符串的 (n(D):n(K))

    (dp_{i,j}) 表示现在 (n(D):n(K)=i:j) 的最多划分组数,那么每加入一个字符之后这个数组的值一定是不降的,证明显然。

    所以我们就可以开一个 map 记录 (dp) 数组的值,扫描字符串的时候更新并输出答案。

    代码:

    // Problem: C. Diluc and Kaeya
    // Contest: Codeforces - Codeforces Round #724 (Div. 2)
    // URL: https://codeforces.ml/contest/1536/problem/C
    // Memory Limit: 256 MB
    // Time Limit: 2000 ms
    // Author: csxsl
    // Created: 2021-06-27 18:11:29
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    #define DC int T = gi <int> (); while (T--)
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
        T f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 500003, M = N << 1;
    
    int n;
    char s[N];
    map <PII, int> dp;
    
    int main()
    {
        //File("");
        DC
        {
        	n = gi <int> ();
        	scanf("%s", s + 1);
        	dp.clear();
        	int sumd = 0, sumk = 0;
        	for (int i = 1; i <= n; i+=1)
        	{
        		if (s[i] == 'D') ++sumd;
        		else ++sumk;
        		int ld = sumd, lk = sumk;
        		int g = __gcd(ld, lk);
        		ld /= g, lk /= g;
        		++dp[{ld, lk}];
        		printf("%d ", dp[{ld, lk}]);
        	}
        	puts("");
        }
        return 0;
    }
    

    D. Omkar and Medians

    题面

    性质:

    • 每次在数列中加入两个数,排序后中位数最多移动一位;
    • 如果一个长度为 (n) 的数列((n) 为奇数)中位数为 (s),那么至少有 (lceilfrac{n}{2} ceil) 个数 (le s)(lceilfrac{n}{2} ceil) 个数 (ge s)

    证明可以考虑分类讨论,这里不再展开。

    考虑 (b_i)(b_{i-1}) 的大小关系:

    • (b_i=b_{i-1}),一定可以满足条件,可以直接插入两个 (b_i)
    • (b_i<b_{i-1}),则已经有 (i-1) 个数 (<b_i),如果之前存在一个 (b_j(j<i)) 满足 (b_i<b_j<b_{i-1}),则已经存在 (i) 个数 (<b_i),不满足题意,直接输出 NO
    • (b_i>b_{i-1}),同理找是否存在一个 (b_j(j<i)) 满足 (b_i>b_j>b_{i-1})

    整个过程可以用 set 实现,要注意细节。

    // Problem: D. Omkar and Medians
    // Contest: Codeforces - Codeforces Round #724 (Div. 2)
    // URL: https://codeforces.ml/contest/1536/problem/D
    // Memory Limit: 256 MB
    // Time Limit: 2000 ms
    // Author: csxsl
    // Created: 2021-06-27 17:54:17
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    #define DC int T = gi <int> (); while (T--)
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
        T f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 200003, M = N << 1;
    
    int n, b[N];
    set <int> s;
    
    int main()
    {
        //File("");
        DC
        {
        	n = gi <int> ();
        	for (int i = 1; i <= n; i+=1) b[i] = gi <int> ();
        	s.clear();
        	s.insert(b[1]);
        	bool fl = true;
        	for (int i = 2; i <= n; i+=1)
        	{
        		auto it1 = s.lower_bound(b[i - 1]), it2 = s.upper_bound(b[i - 1]);
        		bool canmove = false;
        		if (it1 != s.begin()) --it1, canmove = true;
        		if (b[i] > b[i - 1] && (it2 != s.end()) && b[i] > (*it2)) fl = false;
        		if (b[i] < b[i - 1] && canmove && b[i] < (*it1)) fl = false;
        		s.insert(b[i]);
        	}
        	puts(fl ? "YES" : "NO");
        }
        return 0;
    }
    

    E. Omkar and Forest

    题面

    性质:如果确定每个格子填的是 (0) 还是正整数,那么存在唯一的填数方案。

    证明考虑采用反证法,最后可以导出矛盾。这里不再赘述。

    那么每个格子填的数要么是 (0),要么是它与离它最近的 (0) 的曼哈顿距离。

    设有 (k) 个格子为 #,那么答案为 (2^k-[k=n imes m]),因为要减去所有数都是正整数的情况。

    代码:

    // Problem: E. Omkar and Forest
    // Contest: Codeforces - Codeforces Round #724 (Div. 2)
    // URL: https://codeforces.ml/contest/1536/problem/E
    // Memory Limit: 256 MB
    // Time Limit: 2000 ms
    // Author: csxsl
    // Created: 2021-06-27 18:35:57
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    #define DC int T = gi <int> (); while (T--)
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
        T f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 2003, M = N << 1, mod = 1000000007;
    
    int n, m;
    char s[N][N];
    
    int main()
    {
        //File("");
        DC
        {
        	n = gi <int> (), m = gi <int> ();
        	for (int i = 1; i <= n; i+=1) scanf("%s", s[i] + 1);
        	int ans = 1;
        	bool all = true;
        	for (int i = 1; i <= n; i+=1)
        		for (int j = 1; j <= m; j+=1)
        			if (s[i][j] == '0') all = false;
        			else ans = 1ll * ans * 2 % mod;
        	printf("%d
    ", (ans - all + mod) % mod);
        }
        return 0;
    }
    

    F. Omkar and Akmar

    题面

    一道博弈题。

    考虑最终局面,如果有偶数个格子填了数,那么后手获胜;否则先手获胜。

    讨论一下可以发现最终局面只可以是填了偶数个格子。(懒得写证明了

    假设有 (i) 个空格,那么有 (n-i) 个位置要填数,且 (n-i) 为偶数,只能填 BABABABA…… 或者 ABABABAB…… 的样式。

    性质:相邻数之间只能有 (0)(1) 个空格。证明显然。

    那么最多有 (lfloorfrac{n}{2} floor) 个空格,方案数可以使用隔板法求解,为 (inom{n-i}{i})

    确定起点之后,剩下的 (n-i-1) 个格子填充顺序任意,有 ((n-i-1)!) 中方案。

    起点有 (n) 中选法,可以选择 (2) 种填充样式,因此最后答案为

    [2nsumlimits_{i=0}^{lfloorfrac{n}{2} floor}[(n-i)\%2=0]inom{n-i}{i}(n-i-1)! ]

    代码:

    // Problem: F. Omkar and Akmar
    // Contest: Codeforces - Codeforces Round #724 (Div. 2)
    // URL: https://codeforces.ml/contest/1536/problem/F
    // Memory Limit: 256 MB
    // Time Limit: 3000 ms
    // Author: csxsl
    // Created: 2021-06-27 21:18:41
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    #define DC int T = gi <int> (); while (T--)
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    template <typename T>
    inline T gi()
    {
        T f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 1000003, M = N << 1, mod = 1000000007;
    
    int n;
    int fac[N], invfac[N];
    
    inline int qpow(int x, int y)
    {
    	int res = 1;
    	while (y)
    	{
    		if (y & 1) res = 1ll * res * x % mod;
    		x = 1ll * x * x % mod, y >>= 1;
    	}
    	return res;
    }
    
    inline int C(int x, int y)
    {
    	if (x < y) return 0;
    	return 1ll * fac[x] * invfac[x - y] % mod * invfac[y] % mod;
    }
    
    int main()
    {
        //File("");
        n = gi <int> ();
        for (int i = (fac[0] = 1); i <= n; i+=1) fac[i] = 1ll * fac[i - 1] * i % mod;
        invfac[n] = qpow(fac[n], mod - 2);
        for (int i = n - 1; ~i; i-=1) invfac[i] = 1ll * invfac[i + 1] * (i + 1) % mod;
        int sum = 0;
        for (int i = 0; i <= n / 2; i+=1)
        	if ((n - i) % 2 == 0)
        		sum = (1ll * sum + 1ll * C(n - i, i) * fac[n - i - 1] % mod) % mod;
        printf("%d
    ", 1ll * sum * 2 % mod * n % mod);
        return 0;
    }
    

    总结

    一定要善于发现题目性质,分析题目有条理,证明严谨。(当然赛时要大胆猜结论

    参考

    https://blog.csdn.net/xin_jun/article/details/117679904

  • 相关阅读:
    linux初学者-ftp篇(一)
    随机密码生成
    倒计时问题java
    百钱买鸡
    去7JAVA
    贪吃蛇Controller Java实现(二)
    贪吃蛇Global Java实现(二)
    贪吃蛇GamePanel Java实现(二)
    贪吃蛇Listener Java实现(二)
    贪吃蛇snake Java实现(二)
  • 原文地址:https://www.cnblogs.com/xsl19/p/14942566.html
Copyright © 2011-2022 走看看