题目链接:CF|Round246|DIV2
赛后两分钟才搞出C。。真是逗比。
A:简单统计。时间复杂度:O(N)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2010;
int a[N];
int main(){
int n, k;
scanf("%d%d", &n, &k);
int cnt = 0;
for(int i = 0; i < n; ++i){
int x;
scanf("%d", &x);
if(5 - x >= k) ++cnt;
}
printf("%d\n", cnt / 3);
return 0;
}
B:数据较大, 简单模拟会超时。 可以考虑,作为一个队主场(n-1)场肯定是主队,还有可能的是当该队客场比赛时, 颜色与主队一样, 这样只要hash一下同种颜色的主队个数即可。 最后可以根据总的比赛数 - 主队的次数得到客队的次数。时间复杂度O(N)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N];
int x[N];
int main(){
int n, k;
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d%d", &a[i], &b[i]);
++x[a[i]];
}
for(int i = 0; i < n; ++i){
int ans = n - 1 + x[b[i]];
if(a[i] == b[i]) ans -= 1;
printf("%d %d\n", ans, n*2 - 2 - ans);
}
return 0;
}
C:乱搞题。 题意很简单, 就是可以互换之间相隔为质数个数的数字,得到 一个有序的序列。
YY了一个定理:任意一个数都可以由最多5个质数的和表示(原来是哥德巴赫猜想:囧), 刚好最大操作个数<=5*n。
这样先预处理出所有的素数, 每次二分素数, 判断并进行交换。 时间复杂度:O(N*sqrt(N))
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1e6 + 1;
bool isPrime[N];
int a[N], prime[N];
int p[N];
int cnt;
int x[N], y[N];
void gao(){
int k = sqrt(N*1.0);
int i = 2;
while(i <= k){
for(int j = i*i; j < N; j += i) isPrime[j] = 1;
++i;
while(i <= k && isPrime[i]) ++i;
}
for(int i = 2; i < N; ++i){
if(!isPrime[i]) prime[cnt++] = i;
}
}
int foo(int k){
int l = 0, r = cnt - 1;
while(l < r){
int m = (l + r + 1) >> 1;
// printf("m = %d\n", m);
if(prime[m] <= k) l = m;
else r = m - 1;
}
return l;
}
int main(){
int n;
scanf("%d", &n);
gao();
// for(int i = 0; i < 30; ++i) printf("%d ", prime[i]);
for(int i = 1; i <= n; ++i){
scanf("%d", &a[i]);
p[a[i]] = i;
}
// foo(3);
int ans = 0;
for(int i = 1; i <= n; ++i){
int dif = abs(p[i] - i) + 1;
if(p[i] > i){
int tmp = dif;
int xx = p[i], yy = i;
while(tmp != 0){
// printf("%d en\n", tmp);
int k = foo(tmp);
// printf("%d\n",foo(tmp));
x[ans] = xx, y[ans] = xx - prime[k] + 1;
p[a[y[ans]]] = xx;
swap(a[xx], a[y[ans]]);
tmp -= prime[k];
if(tmp != 0) tmp += 1;
xx = y[ans++];
}
}
else if(i > p[i]){
int tmp = dif;
int xx = p[i], yy = i;
while(tmp != 0){
int k = foo(tmp);
x[ans] = xx, y[ans] = xx + prime[k] - 1;
p[a[y[ans]]] = xx;
swap(a[xx], a[y[ans]]);
tmp -= prime[k];
if(tmp) ++tmp;
xx = y[ans++];
}
}
}
printf("%d\n", ans);
for(int i = 0; i < ans; ++i){
if(x[i] < y[i]) printf("%d %d\n", x[i], y[i]);
else printf("%d %d\n", y[i], x[i]);
}
return 0;
}