Codeforces Round 347 div1
通过数: 0
A:
/*
就是整数划分之类问题
注意几个坑点
负数不是都取-1,可能取n来满足过多正数的条件
自己的解法是在选取正数都取1(负数都取-1),负数(正数)需要满足等式的最大值。
这样正数(负数类似)可以分成三个部分
一是值为n的部分,一是中间值部分,一是值为1的部分
遗憾的是赛中中间值部分值大于n时未作处理……
标程是利用合法性进行暴力求解的方法,比这个好~
*/
#include
using namespace std;
const int MAXN = 1e4 + 5;
char str[MAXN];
int main()
{
while(fgets(str, MAXN, stdin)) {
int t1 = str[0] == '-' ? 0 : 1, t2 = 0;
int flag = 0;
int n = 0;
for(int i = 0 ; i < strlen(str) ; i++) {
if(flag) {
if(str[i] >= '0' && str[i] <= '9') n = n * 10 + str[i] - '0';
}
else {
if(str[i] == '=') flag = 1;
else if(str[i] == '-') t2++;
else if(str[i] == '+') t1++;
}
}
if(t1 * n < t2 + n || t1 > t2 * n + n) puts("Impossible");
else {
puts("Possible");
int sign = 1;
int cnt1, cnt2;
cnt1 = 0; cnt2 = 0;
int orgn = max(n + t2, t1);
int num1 = 0;
if(n != 1) {
while((num1 + 1) * n + n + t1 - num1 - 2 <= orgn) num1++;
}
int pre1 = n;
int last1 = 1;
int mid1 = orgn - num1 * pre1 - (t1 - num1 - 1);
while(num1 >= 0 && mid1 <= 0) num1--, mid1 += n - 1;
while(mid1 > n) mid1 -= n - 1, num1++;
int num2 = 0;
if(n != 1) {
while(pre1 * num1 + mid1 + (t1 - num1 - 1) - ((n * (num2 + 1) + n + t2 - num2 - 2)) >= n) {
// printf("f1 = %d, f2 = %d\n", pre1 * num1 + mid1 + (t1 - num1 - 1), (n * (num2 + 1) + n + t2 - num2 - 2));
num2++;
}
}
int pre2 = n;
int last2 = 1;
int mid2 = n + num2 * pre2 + (t2 - num2 - 1) - (pre1 * num1 + mid1 + (t1 - num1 - 1));
mid2 = -mid2;
// printf("pre2 = %d, mid2 = %d\n", pre2, mid2);
// printf("mid1 = %d\n", mid1);
// printf("num1 = %d, num2 = %d\n", num1, num2);
while(num2 >= 0 && mid2 <= 0) num2--, mid2 += n - 1;
while(mid2 > n) num2++, mid2 -= n - 1;
// printf("num1 = %d, num2 = %d\n", num1, num2);
// printf("num1 = %d, pre = %d, mid = %d, last = %d\n", num1, pre, mid, last);
for(int i = 0 ; i < strlen(str) ; i++) {
if(str[i] == '?') {
if(sign == 1) {
if(cnt1 < num1) printf("%d", pre1);
else if(cnt1 == num1) printf("%d", mid1);
else printf("%d", last1);
cnt1++;
}
else {
if(cnt2 < num2) printf("%d", pre2);
else if(cnt2 == num2) printf("%d", mid2);
else printf("%d", last2);
cnt2++;
}
}
else {
if(str[i] == '-') sign = -1;
if(str[i] == '+') sign = 1;
printf("%c", str[i]);
}
}
puts("");
}
}
return 0;
}
/*
? + ? + ? + ? - ? = 2
*/
B:
/*
首先明白题意是后几位未出现数字,也就是会有IAO’09这种情况出现
然后发现两位数在一个区间长度为100的连续区间内,三位数在长度1000的连续区间内
且所有区间按区间大小从小到大排列
对于一个k位数,它的最小值是1989+(10^(k-1) + 10^(k-2) + … + 10)
因为尾k位数是确定的,所以它每次只在最前面加上10^k这个数,直到大于等于最小值
*/
#include
using namespace std;
#define LL long long
char str[20];
int main()
{
int n;
while(scanf("%d", &n) != EOF) {
while(n--) {
scanf("%s", str);
int k = strlen(str + 4);
LL ans = atoi(str + 4);
int F = 0;
int ten = 10;
for(int i = 1 ; i < k ; i++) {
F += ten; ten *= 10;
}
while(ans < F + 1989) ans += ten;
cout << ans << endl;
}
}
return 0;
}
C:
/*
首先确定是要留下哪一种颜色
然后对每个连通块,确定一点一定要取之后,可以根据边颜色的合法性判断下一个未访问点是否需要使用
以及如果下一个点是已访问点,需要进行合法性判断
然后每个连通块取当前假设要取的点和不取点里的最小值,可以用最小二分染色理解。
*/
#include
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef pair<int,int> pii;
const int MAXN = 1e5 + 5;
int color[MAXN], tcolor[MAXN];
int vis[MAXN], vis2[MAXN];
int use[MAXN];
int n, m;
vector e[MAXN];
pii bfs(int st, int c)
{
// printf("st = %d\n", st);
int tot = 1;
queue<int> que;
vis[st] = 1; use[st] = 1;
for(auto p : e[st]) {
vis[p.fi] = 1; que.push(p.fi);
if(color[p.se] == c) use[p.fi] = 1;
else use[p.fi] = 0;
}
int res = 1;
while(!que.empty()) {
tot++;
int u = que.front(); que.pop();
if(use[u]) res++;
for(auto p : e[u]) {
int v = p.fi, mark = p.se;
if(vis[p.fi] == 0) {
if(use[u] == (color[p.se] == c)) use[p.fi] = 1;
vis[p.fi] = 1;
que.push(p.fi);
}
else if((use[u] + use[p.fi]) % 2 == (color[p.se] == c)) {
// printf("u = %d, p.fi = %d, c = %d\n", u, p.fi, c);
// printf("use[u] = %d, use[p.fi] = %d, color[p.se] = %d\n", use[u], use[p.fi], color[p.se]);
// system("pause");
return mp(tot, -1);
}
}
}
if(tot - res < res) {
que.push(st);
vis2[st] = 1;
while(!que.empty()) {
int u = que.front(); que.pop();
use[u] = use[u] == 1 ? 0 : 1;
for(auto p : e[u]) {
if(vis2[p.fi] == 0) que.push(p.fi), vis2[p.fi] = 1;
}
}
}
return mp(tot, res);
}
int solve(int c)
{
memset(vis, 0, sizeof vis);
memset(vis2, 0, sizeof vis2);
memset(use, 0, sizeof use);
int res = 0;
for(int i = 1 ; i <= n ; i++) {
if(vis[i] == 0) {
pii temp = bfs(i, c);
if(temp.se == -1) return -1;
else {
// printf("temp.fi = %d, temp.se = %d\n", temp.fi, temp.se);
res += min(temp.fi - temp.se, temp.se);
}
}
}
return res;
}
int use1[MAXN], use2[MAXN];
int main()
{
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 1 ; i <= n ; i++) e[i].clear();
for(int i = 1 ; i <= m ; i++) {
char str[10];
int u, v; scanf("%d%d%s", &u, &v, str);
e[u].pb(mp(v, i)); e[v].pb(mp(u, i));
if(str[0] == 'R') color[i] = 1;
else color[i] = -1;
}
int ans = n + 1;
int t1 = solve(1);
if(t1 != -1) ans = min(ans, t1);
memcpy(use1, use, sizeof use);
int t2 = solve(-1);
if(t2 != -1) ans = min(ans, t2);
memcpy(use2, use, sizeof use);
// printf("t1 = %d, t2 = %d\n", t1, t2);
if(ans == n + 1) puts("-1");
else {
printf("%d\n", ans);
if(ans == t1) {
int f = 1;
for(int i = 1 ; i <= n ; i++) {
if(use1[i] == 0) continue;
if(f) f = 0;
else printf(" ");
printf("%d", i);
}
puts("");
}
else {
int f = 1;
for(int i = 1 ; i <= n ; i++) {
if(use2[i] == 0) continue;
if(f) f = 0;
else printf(" ");
printf("%d", i);
}
puts("");
}
}
}
return 0;
}