Codeforces 922C 922D 题解

<C>

题意:

给一个数 n,再给一个数 k,问是否存在数对 <i,  j> 满足:

(1) 1 <= i < j <= k

(2) n % i == n % j

若存在数对,就不符合题意打印No, 否则打印Yes。

思路:

我们ACM一个大佬,就是我师父YJH143,他说和中国剩余定理有关,我不懂,就大暴力过的,数据1e18的,当时怂了想写个O(1)的,发现一直写不出来,于是搏一搏单车变摩托,写了个1e9的,主要就是看在k之前,哪个值tmp不满足 n % tmp == tmp - 1,那k >= tmp时就都会挫掉。但我进行了大概是多余的特判,说下我大体思路:

k == 1时,显然满足题意,打印Yes;

k == 2时,如果输入的n是偶数就不满足,否则满足;

接下来就是 k>= 3的情况了,先看 n 与 k 的关系,如果 n >= k,就不满足,否则,如果n是偶数就不满足,

接下来情况就更改为:n >= 3 且 k > n 且 k 为奇数时何时满足。

然后我就写了一个1e9的循环,就结束了,如下:

int pos = 0;
for(int i = 1; i <= 1e9; i++) {
    if(n % i != i - 1) {
        pos = i; break;    
    }
}

if(k >= pos) flg = 0;

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n, k;

int main() {
    cin >> n >> k;
    bool flg = 1;
    if(k == 1) {
        puts("Yes");
        return 0;
    }
    else if(k == 2) {
        if(n & 1) puts("Yes");
        else puts("No");
        return 0;
    }
    else { // k >= 3
        if(k >= n) flg = 0;
        else { // n >= 4
            if(!(n & 1)) flg = 0;
            else {
                int pos = 0;
                for(int i = 1; i <= 1e9; i++) {
                    if(n % i != i - 1) {
                        pos = i; break;
                    }
                }
                if(k >= pos) flg = 0;
            }
        }
    }
    if(flg) puts("Yes");
    else puts("No");

}


我是将1e9当临界值判了,我师父把临界值当100做的,黑科技啊,放一下我师父YJH143的代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
typedef long long LL;

bool vis[105];
int main() 
{
	LL n, K;
	while(~scanf("%I64d%I64d", &n, &K)) {
		memset(vis, 0, sizeof(vis));
		if(K >= 100) printf("NO\n");
		else {
			bool ok = 1;
			for (int i = 1; i <= K; i++) {
				int x = n % i; if(vis[x]) ok = 0;
				vis[x] = 1;
			}
			if(ok) printf("YES\n"); else printf("NO\n");
		}
	}
	return 0;
}


<D>

题意:

给定 n 个只由 h 和 s ,组成的串,将他们以某种顺序连接在一起,问他们能组成的非连续子串 'sh' 的个数最大是多少。

思路:

这题标签写了排序,最开始我也想从结构体排序入手,这题是我师父 YJH143 的女票教我的,也就是我师娘 yyt 啦,那就大体说下我师娘给我讲的的思路 ~ 首先我们考虑一下,给定的这些串,经过何种顺序排序连接起来,能使它提供的'sh'个数最多,先用两个串 x 和 y 举例子:

以x在前y在后的连接方式所能提供的'sh',即(x --> y).sh = x.sh + y.sh + x.s * y.h;

以y在前x在后的连接方式所能提供的'sh',即(y --> x).sh = y.sh + x.sh + y.s * x.h;

所以直接在结构体里记一个ans,按照上述排序方式操作即可,由于我只会写最简单的结构体sort,所以师娘给我操作了一把,我现在略知一二,操作如下:

bool cmp(PP x, PP y) {
    x.ans = x.sh + y.sh + x.s * y.h;
    y.ans = y.sh + x.sh + y.s * x.h;
    return x.ans > y.ans;

}

接下来的问题,就是怎么求每个串能提供的'sh'数,答案显然是倒序枚举啦,从后往前找,找到一个 'h',就a[i].h++; 找到一个 's',就先执行 a[i].s++,然后这时候能提供的'sh'数,就a[i].sh += a[i].h 即可,因为你每找到一个's',都能和它后面所有的 'h' 配对形成'sh',这也是倒序枚举的意义所在,具体操作如下:

    for(int i = 1; i <= n; i++) { //计算每个串能提供的sh数
        cin >> a[i].ss;
        int l = a[i].ss.length();
        for(int j = l - 1; j >= 0; j--) {
            if(a[i].ss[j] == 'h') a[i].h++;
            else {
                a[i].s++;
                a[i].sh += a[i].h;
            }
        }

    }

然后根据你刚才声明的cmp, 进行sort()排序,再按照上述方法倒序求'sh'数即可。

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
int n;

struct PP {
    string ss;
    ll s, h, sh;
    ll ans;
} a[maxn];

bool cmp(PP x, PP y) {
    x.ans = x.sh + y.sh + x.s * y.h;
    y.ans = y.sh + x.sh + y.s * x.h;
    return x.ans > y.ans;
}

int main() {
    cin >> n;
    for(int i = 1; i <= n; i++) { //计算每个串能提供的sh数
        cin >> a[i].ss;
        int l = a[i].ss.length();
        for(int j = l - 1; j >= 0; j--) {
            if(a[i].ss[j] == 'h') a[i].h++;
            else {
                a[i].s++;
                a[i].sh += a[i].h;
            }
        }
    }
    sort(a + 1, a + n + 1, cmp);
    ll res = 0;
    ll num = 0;
    for(int i = n; i >= 1; i--) {
        int l = a[i].ss.length();
        for(int j = l - 1; j >= 0; j--) {
            if(a[i].ss[j] == 'h') num++;
            else res += num;
        }
    }
    cout << res << endl;
}

猜你喜欢

转载自blog.csdn.net/ericgipsy/article/details/80600982