- 漂亮字符串
如果maxO == 0 说明只有x, 答案就是maxX
如果X不够用,说明每次都是放maxO个O,用一个X隔开 OOOOOXOOOOOX.....
此时有countO >= (countX + 1) * maxO
因此,最大是countX + (countX + 1) * maxO;
注意更新
#include <iostream>
#include <cstdio>
long long CountO, CountX, maxO, maxX;
int main() {
freopen("bs.in","r",stdin);
freopen("bs.out","w",stdout);
while (scanf("%lld%lld%lld%lld", &CountO, &CountX, &maxO, &maxX)) {
maxX = std::min(maxX, CountX);
maxO = std::min(maxO, CountO);
if (maxO == 0)
printf("%lld\n", maxX);
else if (maxX == 0)
printf("%lld\n", maxO);
else if (CountO > (CountX + 1) * maxO)
printf("%lld\n",CountX + (CountX + 1) * maxO);
else if (CountX > (CountO + 1) * maxX)
printf("%lld\n", CountO + (CountO + 1) * maxX);
else
printf("%lld\n", CountX + CountO);
}
return 0;
}
2.Set
一个线性筛 + 并查集 (有倍数关系)
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 100001;
bool pflag[maxn];
int prime[maxn>>1];
int fa[maxn];
int A, B;
int prime_cnt = 0;
int ans;
int P;
inline void Prime_Filter() {
for (int i = 2; i <= B; ++ i){
if(!pflag[i]) prime[ ++ prime_cnt] = i;
for (int j = 1; j <= prime_cnt && prime[j] * i <= B; ++ j){
pflag[prime[j] * i] = true;
if ( i % prime[j] == 0) break;
}
}
}
inline int getRoot(int x) {
if (x == fa[x]) return x;
return fa[x] = getRoot(fa[x]);
}
bool judgeEqual(int x,int y) {
return getRoot(x)==getRoot(y);
}
inline void join(int x,int y) {
x = getRoot(x), y = getRoot(y);
fa[y] = x;
}
inline void init() {
cin >> A >> B >> P;
ans = 0;
for (int i = 1; i <= B; ++ i) {
fa[i] = i;
}
Prime_Filter();
}
inline void solve() {
int begin = 1;
for (; prime[begin] < P; ++ begin);
for (int k = prime[begin]; k <= B && k > 1; k = prime[++ begin]){
for (int i = A/k*k, start = i; i <= B; start = i, i += k) {
if (i < A || start < A) continue;
if(!judgeEqual(i,start)) {
join(i,start);
}
}
}
for (int i =A; i <= B; ++ i)
if (fa[i] == i) ans ++;
}
int main() {
freopen("set.in","r",stdin);
freopen("set.out","w",stdout);
init();
solve();
cout << ans;
}
3.Prison
动态规划经典题目,考的时候没有想出来优化,A得很水。。。。
用DP[i][j]表示在[i,j]区间所有该被释放的人都被释放的最小支付代价。
若是释放k,那么代价为DP[i][k-1]+DP[k+1][j]+(j-i)
这里的sum[i]指的是前i个位置中有多少犯人无法被释放。
#include <iostream>
#include <cstdio>
#include <algorithm>
const int MAX = 1010;
const int Inf = 0x7fffffff;
int n, m, a[MAX], sum[MAX], DP[MAX][MAX];
inline void init() {
for (int i = 0; i < MAX; ++ i) {
std::fill(DP[i], DP[i] + MAX, Inf);
DP[i][i] = 0;
}
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++ i)
scanf("%d", &a[i]);
std::sort(a + 1, a + m + 1);
for (int i = 1; i <= m; ++ i)
sum[i] = a[i] - a[i - 1] - 1;
sum[m + 1] = n - a[m];
for (int i = 1; i <= m + 1; ++ i)
sum[i] = sum[i] + sum[i-1];
}
inline void solve() {
for (int i = m + 1; i >= 1; -- i)
for (int j = i + 1; j <= m + 1; ++ j)
for (int k = i; k < j; ++ k)
DP[i][j] = std::min(DP[i][j], DP[i][k] + DP[k + 1][j] + sum[j] - sum[i - 1] + j - i - 1);
}
int main() {
freopen("prison.in","r",stdin);
freopen("prison.out","w",stdout);
init();
solve();
printf("%d\n", DP[1][m+1]);
return 0;
}
4.Tree
这个还在打,待会传。