C - Minimization
第一次可能有多种选择,我们枚举所有的选择,然后两边贪心取即可。
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
int n, k;
void run() {
int p;
for(int i = 1; i <= n; i++) {
int x; cin >> x;
if(x == 1) p = i;
}
int ans = N;
for(int i = 1; i <= n; i++) {
int l = i, r = min(n, i + k - 1);
if(l <= p && p <= r)
ans = min(ans, 1 + (l - 1 + k - 2) / (k - 1) + (n - r + k - 2) / (k - 1));
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
while(cin >> n >> k) run();
return 0;
}
D - Snuke Numbers
这个就是打表找规律...但规律也不是很好找,这个规律是变换的规律,可能一次加上\(10^i\),也可以加上\(10^{i+1}\),两个判断一下即可。
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
int K;
double Snuke(ll x) {
ll tmp = 0, c = x;
while(c) {
tmp += c % 10;
c /= 10;
}
return 1.0 * x / tmp;
}
void run() {
ll res = 0, x = 1;
while(K--) {
double t1, t2;
while(true) {
t1 = Snuke(res + x), t2 = Snuke(res + x * 10);
if(t1 <= t2) break;
x *= 10;
}
res += x;
cout << res << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
while(cin >> K) run();
return 0;
}
E - Independence
题意:
给出\(n\)个点\(m\)条无向边,现在对于任意两个点,至多有一条边直接连接。
现在要将这个图划分为两部分,使得两部分都为完全图,问最终每部分最小边数之和为多少。
思路:
- 划分为两部分之后的答案很好计算,假设两边的点分别有\(x,y\)个,那么最终答案就为\(\frac{x\cdot (x-1)}{2}+\frac{y\cdot (y-1)}{2}\)。
- 现在就考虑如何划分。
- 我们取原图的补图,那么最终两个集合中不存在任何一条边即符合条件。
- 进一步地,我们将这个与二分图等价,其实就将问题转化为二分图问题了。
- 首先判断二分图是否存在,若存在,先有若干个连通块,每个连通块有两种选择,那么直接背包\(dp\)一下求出最终所有方案数就行了。
(一开始还以为能够滚动一维QAQ)
代码如下:
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 705;
int n, m;
bool lnk[N][N];
int cnt[2];
int col[N];
bool f;
void dfs(int u, int c) {
col[u] = c;
++cnt[c];
for(int v = 1; v <= n; v++) {
if(lnk[u][v]) {
if(col[v] == -1) dfs(v, 1 - c);
else if(col[v] == c) {
f = false;
return;
}
}
}
}
pii num[N];
bool dp[N][N];
void run() {
memset(col, -1, sizeof(col));
memset(dp, 0, sizeof(dp));
f = true;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
if(i != j) lnk[i][j] = 1;
}
for(int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
lnk[u][v] = lnk[v][u] = 0;
}
int tot = 0;
for(int i = 1; i <= n; i++) {
if(col[i] == -1) {
cnt[0] = cnt[1] = 0;
dfs(i, 0);
num[++tot] = MP(cnt[0], cnt[1]);
}
}
if(f == false) {
cout << -1 << '\n';
return;
}
dp[0][0] = 1;
for(int i = 1; i <= tot; i++) {
for(int j = 0; j <= n; j++) {
if (j >= num[i].fi) dp[i][j] |= dp[i - 1][j - num[i].fi];
if (j >= num[i].se) dp[i][j] |= dp[i - 1][j - num[i].se];
}
}
int ans = 1e9;
for(int i = 0; i <= n; i++) {
if(dp[tot][i]) {
ans = min(ans, i * (i - 1) / 2 + (n - i) * (n - i - 1) / 2);
}
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
while(cin >> n >> m) run();
return 0;
}
F - Eating Symbols Hard
待补。