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