A. Arithmetic Array
代码
#include <iostream>
using namespace std;
int main() {
int T;
cin>>T;
while(T--) {
int n;
cin>>n;
int sum=0;
for(int i=1;i<=n;++i) {
int x;
cin>>x;
sum+=x;
}
if(sum==n) cout<<0<<endl;
else if(sum<n) cout<<1<<endl;
else cout<<sum-n<<endl;
}
}
B. Bad Boy
题解
最大可以让这个人走 n + n + m + m − 4 n+n+m+m-4 n+n+m+m−4
代码
#include <iostream>
using namespace std;
int main() {
int T;
cin >> T;
while(T--) {
int n, m, i, j;
cin >> n >> m >> i >> j;
cout<< 1 << ' ' << 1 << ' ' << n << ' '<< m <<endl;
}
return 0;
}
C. Challenging Cliffs
题解
找到任意一对绝对值最小的数
(
i
,
i
+
1
)
(i,i+1)
(i,i+1),这样满足第一个条件最优。
原本升序输出可以得
n
−
1
n-1
n−1分,但是
(
i
,
i
+
1
)
(i,i+1)
(i,i+1)被分开,最多可以得
n
−
2
n-2
n−2分
答案输出
a
[
i
+
1...
n
]
a
[
1...
i
]
a[i+1...n] a[1...i]
a[i+1...n]a[1...i]
(读错题,wa了一辈子)
代码
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
const int N=200010;
int a[N];
int main() {
int T;
scanf("%d",&T);
while(T--) {
int n, tot = 0, num = 0;
scanf("%d",&n);
for(int i = 1; i <= n; ++ i) scanf("%d",&a[i]);
sort(a + 1,a + 1 + n);
if(n > 2) {
int sub = 1e9, ii;
for(int i = 1;i < n; ++ i) {
if(a[i + 1] - a[i] < sub) sub = a[i + 1] - a[i], ii = i;
}
for(int i = ii + 1; i <= n; ++ i) cout << a[i] << ' ';
for(int i = 1; i <= ii; ++ i) cout << a[i] << ' ';
}
else {
for(int i = 1; i <= n; ++ i) cout << a[i] << ' ';
}
cout << endl;
}
return 0;
}
D. Deleting Divisors
题解
打表找规律。
n
n
n是奇数 Bob赢
n
n
n是偶数 且不是
2
2
2的幂次 Alice赢
n
n
n是偶数 且是
2
2
2的幂次 如果
l
o
g
2
(
n
)
log2(n)
log2(n)是奇数 Bob赢 否则 Alice赢
代码
#include <iostream>
#include <algorithm>
#include <set>
#include <cmath>
using namespace std;
const int N=10000010;
int f[N][2];
/*打表代码*/
int dfs(int x,int y) {
if(f[x][y]!=-1) return f[x][y];
f[x][y]=0;
for(int j=2;j*j<=x;++j) {
if(x%j==0) {
int k=x/j;
if(!dfs(x-j,1-y)) f[x][y]=1;
if(!dfs(x-k,1-y)) f[x][y]=1;
}
}
return f[x][y];
}
int main() {
int T;
cin>>T;
// for(int i=0;i<N;++i) f[i][0]=f[i][1]=-1;
// for(int i=1;i<199;++i) {
// if(dfs(i,0));
// else if(i%2==0) cout<<i<<endl;
// }
while(T--) {
int n;
cin>>n;
if(n%2) puts("Bob");
else {
int ans=-1;
for(int i=1;i<=30;++i) {
if(n==(1<<i) ) {
ans=i;
break;
}
}
if(ans!=-1) {
if(ans%2==0) puts("Alice");
else puts("Bob");
}
else puts("Alice");
}
}
return 0;
}
E1. Erase and Extend (Easy Version)
题解
首先确定一种策略,先将
s
s
s删除变成成
s
′
s'
s′,然后复制s’再将多余
k
k
k的字母删除。问题就是如果得到
s
′
s'
s′.
e
1
e1
e1可以
O
(
n
2
)
O(n^2)
O(n2)枚举。
还有一个单调性,如果
s
[
1
,
l
e
n
]
+
s
[
1
,
l
e
n
]
+
.
.
.
<
s
[
1
,
n
+
s
[
1
,
n
]
+
.
.
.
s[1,len]+s[1,len]+...<s[1,n+s[1,n]+...
s[1,len]+s[1,len]+...<s[1,n+s[1,n]+...,那么有
s
[
1
,
l
e
n
]
+
s
[
1
,
l
e
n
]
+
.
.
.
<
s
[
1
,
i
]
+
s
[
1
,
i
]
+
.
.
.
s[1,len]+s[1,len]+...<s[1,i]+s[1,i]+...
s[1,len]+s[1,len]+...<s[1,i]+s[1,i]+...对于所有
l
e
n
<
i
len<i
len<i (不确定)
如果要
s
′
=
s
[
1...
l
e
n
]
s'=s[1...len]
s′=s[1...len],就有
s
[
l
e
n
+
1..
n
]
+
s
>
s
[
1..
n
]
s[len+1..n]+s>s[1..n]
s[len+1..n]+s>s[1..n],kmp预处理
s
[
i
]
s[i]
s[i]的
n
e
x
t
next
next数组,从前向后枚举要删除包括
i
i
i,最小的删除下标是多少,
j
=
n
e
[
i
−
1
]
+
1
j=ne[i-1]+1
j=ne[i−1]+1,比较
s
[
j
]
s[j]
s[j]和
s
[
j
]
s[j]
s[j],也就是比较
s
[
1...
j
]
s[1...j]
s[1...j]和
s
[
i
−
j
+
1...
i
]
s[i-j+1...i]
s[i−j+1...i]的大小。
代码
#include <iostream>
using namespace std;
const int N = 5010;
int n, k;
char str[N];
bool cmp(int x,int y) {
int i = 1, j = 1, t = k;
while(--t) {
if(str[i] < str[j]) return true;
if(str[i] > str[j]) return false;
++i , ++j;
if(i > x) i = 1;
if(j > y) j = 1;
}
return true;
}
int main() {
cin >> n >> k;
cin >> (str+1);
int len = n;
for (int i = n; i >= 1; --i) {
if(cmp(i,len)) {
len = i;
}
}
for(int i = 1, j=1; i <= k; ++i) {
cout << str[j];
if(++j > len) j=1;
}
}
E2. Erase and Extend (Hard Version)
代码
#include <iostream>
using namespace std;
const int N = 500010;
int n, k, ne[N];
char str[N];
int main() {
cin >> n >> k;
cin >> (str + 1);
for(int i = 1; i <= n; ++ i) str[i + n] = str[i];
for(int i = 2, j = 0; i <= n*2; ++ i) {
while (j && str[i] != str[j + 1] ) j = ne[j];
if( str[i] == str[j + 1]) ++ j;
ne[i] = j;
}
int len = n;
for(int i = 1; i <= n * 2; ++i) {
int j = ne[i - 1] + 1;
if( str[j] < str[i] ) {
cout<<i<<' '<<j<<endl;
len = i - j;
break;
}
}
for(int i = 1, j=1; i <= k; ++i) {
cout << str[j];
if(++j > len) j=1;
}
}