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;
}

發佈了84 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章