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>usingnamespace std;typedeflonglong 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");}}return0;}
<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;
}