2012 Regional Changchun Site
部分题目:
比赛队友过掉的题目,没有过掉但有可能过掉的题目。。。
B:
傻逼2-sat题,据说是道poj原题,共有31位,对每一位进行2-sat判一下。fuck,一个很坑人的trick,给的b[][]不一定是合法的。如果不合法,直接输出NO
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n)for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h)for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l)for((i) = (h); (i) >= (l); --(i)) #define L(x)(x) << 1 #define R(x)(x) << 1 | 1 #define MID(l, r)(l + r) >> 1 #define Min(x, y)x < y ? x : y #define Max(x, y)x < y ? y : x #define E(x)(1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x)printf("%I64d\n", x) #define lowbit(x)(x)&(-x) #define Read()freopen("data.in", "r", stdin) #define Write()freopen("data.out", "w", stdout); const double eps = 1e-8; typedef long long LL; const int inf = ~0u>>2; using namespace std; const int maxn = 1024; struct node { int to; int next; } g[maxn*maxn]; int head[maxn], t; int n, b[maxn>>1][maxn>>1]; int scc[maxn], dfn[maxn], low[maxn], s[maxn]; bool vis[maxn]; int ind, cnt, top; void init() { for(int i = 0; i < maxn; i++) { scc[i] = dfn[i] = low[i] = vis[i] = 0; head[i] = -1; } ind = cnt = top = t = 0; } void add(int u, int v) { g[t].to = v; g[t].next = head[u]; head[u] = t++; } void build_mp(int p) { int i, j; init(); //printf("%d\n", p); for(i = 0; i < n; ++i) { for(j = 0; j < n; ++j) { if(i == j) continue; if(i%2 == 1 && j%2 == 1) { if(b[i][j]&(1<<p)) { add(i, j + n); add(j, i + n); } else { add(i + n, i); add(j + n, j); } } else if(i%2 == 0 && j%2 == 0) { if(b[i][j]&(1<<p)) { add(i, i + n); add(j, j + n); } else { add(i + n, j); add(j + n, i); } } else { if(b[i][j]&(1<<p)) { add(i, j + n); add(j, i + n); add(i + n, j); add(j + n, i); } else { add(i, j); add(j, i); add(i + n, j + n); add(j + n, i + n); } } } } } void dfs(int u) { int v, i; dfn[u] = low[u] = ++ind; s[++top] = u; vis[u] = true; for(i = head[u]; i != -1; i = g[i].next) { v = g[i].to; if(!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if(vis[v]) { low[u] = min(low[u], dfn[v]); } } if(dfn[u] == low[u]) { //puts("here"); cnt++; do { v = s[top--]; //printf("%d %d\n", v, cnt); scc[v] = cnt; vis[v] = false; } while(v != u); } } void tarjan(int n) { for(int i = 0; i < n; ++i) { if(!dfn[i]) dfs(i); } } bool solve(int n) { tarjan(n<<1); for(int i = 0; i < n; ++i) { if(scc[i] == scc[i+n]) return false; } return true; } bool DO() { int i, j, p; for(i = 0; i < n; ++i) { //trick for(j = 0; j < n; ++j) { if(i == j && b[i][j] != 0) return false; if(b[i][j] != b[j][i]) return false; } } for(p = 0; p < 31; ++p) { build_mp(p); if(!solve(n)) return false; } return true; } int main() { //freopen("data.in", "r", stdin); int i, j; while(~scanf("%d", &n)) { for(i = 0; i < n; ++i) { for(j = 0; j < n; ++j) { scanf("%d", &b[i][j]); } } if(DO()) puts("YES"); else puts("NO"); } return 0; }
C:
乱搞题,比赛的时候我搞的,弄清楚题意就会发现这是一道水题。。。
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n)for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h)for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l)for((i) = (h); (i) >= (l); --(i)) #define L(x)(x) << 1 #define R(x)(x) << 1 | 1 #define MID(l, r)(l + r) >> 1 #define Min(x, y)x < y ? x : y #define Max(x, y)x < y ? y : x #define E(x)(1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x)printf("%I64d\n", x) #define lowbit(x)(x)&(-x) #define Read()freopen("data.in", "r", stdin) #define Write()freopen("data.out", "w", stdout); const double eps = 1e-8; typedef long long LL; const int inf = ~0u>>2; using namespace std; const int maxn = 200010; LL cnt[maxn]; int parent[maxn]; LL tol[maxn]; struct node { int u, v, w; bool operator < (const node cmp) const { return this->w > cmp.w; } }p[maxn]; int find(int x) { return parent[x] == x ? x : (parent[x] = find(parent[x]));} int main() { // freopen("data.in", "r", stdin); int n, i,a , b, c; while(~scanf("%d", &n)) { for(i = 0; i < n - 1; ++i) { scanf("%d%d%d", &p[i].u, &p[i].v, &p[i].w); } sort(p, p + n - 1); for(i = 0; i <= n; ++i) { cnt[i] = 1; tol[i] = 0; parent[i] = i; } for(i = 0; i < n - 1; ++i) { a = p[i].u; b = p[i].v; c = p[i].w; a = find(a); b = find(b); if(a == b) continue; LL t1 = cnt[a]*c + tol[b]; LL t2 = cnt[b]*c + tol[a]; if(t1 >= t2) { parent[a] = b; tol[b] = t1; cnt[b] += cnt[a]; } else { parent[b] = a; tol[a] = t2; cnt[a] += cnt[b]; } } LL ans = tol[1]; for(i = 2; i <= n; ++i) { ans = max(ans, tol[i]); } printf("%lld\n", ans); } return 0; }
H:
我太弱了,比赛的时候队友跟我讨论。。。我没看懂。。。对不起队友了。。。T_T
发现两个点dp就很明确了:
1、Ai是m的约数。
2、LCM(Ai, Aj)也是m的约数。
把所有m的约数找出来,状态压缩dp。。。
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n)for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h)for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l)for((i) = (h); (i) >= (l); --(i)) #define L(x)(x) << 1 #define R(x)(x) << 1 | 1 #define MID(l, r)(l + r) >> 1 #define Min(x, y)x < y ? x : y #define Max(x, y)x < y ? y : x #define E(x)(1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x)printf("%I64d\n", x) #define lowbit(x)(x)&(-x) #define Read()freopen("data.in", "r", stdin) #define Write()freopen("data.out", "w", stdout); const double eps = 1e-8; typedef long long LL; const int inf = ~0u>>2; using namespace std; const int N = 1024; const int MOD = 1e9+7; int dp[2][N][110]; int pnum[N]; int pos[N]; int LCM[N][N]; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } int lcm(int a, int b) { return a/gcd(a, b)*b; } int main() { //freopen("data.in", "r", stdin); int i, j, k, l; for(i = 1; i < N; ++i) { for(j = i; j < N; ++j) { LCM[j][i] = LCM[i][j] = lcm(i, j); } } int n, m, K, cnt; while(~scanf("%d%d%d", &n, &m, &K)) { CL(pos, -1); cnt = 0; for(i = 1; i <= m; ++i) { if(m%i == 0) { pnum[cnt] = i; pos[i] = cnt++; } } CL(dp, -1); for(i = 0; i < cnt; ++i) { dp[1][pnum[i]][pos[pnum[i]]] = 1; } for(k = 2; k <= K; ++k) { for(i = k - 1; i <= n; ++i) { //Ai are all positive numbers for(j = 0; j < cnt; ++j) { if(dp[(k-1)&1][i][j] == -1) continue; for(l = 0; l < cnt && i + pnum[l] <= n; ++l) { int pp = LCM[pnum[j]][pnum[l]]; if(pos[pp] == -1) continue; pp = pos[pp]; if(dp[k&1][i + pnum[l]][pp] == -1) dp[k&1][i + pnum[l]][pp] = dp[(k-1)&1][i][j]; else dp[k&1][i + pnum[l]][pp] += dp[(k-1)&1][i][j]; if(dp[k&1][i + pnum[l]][pp] >= MOD) dp[k&1][i + pnum[l]][pp] -= MOD; } } } CL(dp[(k-1)&1], -1); } int ans; if(dp[K&1][n][cnt-1] == -1) ans = 0; else ans = dp[K&1][n][cnt-1]; printf("%d\n", ans); } return 0; }
K:
乱搞,枚举r,二分k,注意过程会超long long ,比赛的时候跪了3次。。
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n)for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h)for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l)for((i) = (h); (i) >= (l); --(i)) #define L(x)(x) << 1 #define R(x)(x) << 1 | 1 #define MID(l, r)(l + r) >> 1 #define Min(x, y)x < y ? x : y #define Max(x, y)x < y ? y : x #define E(x)(1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x)printf("%I64d\n", x) #define lowbit(x)(x)&(-x) #define Read()freopen("data.in", "r", stdin) #define Write()freopen("data.out", "w", stdout); const double eps = 1e-8; typedef long long LL; const int inf = ~0u>>2; using namespace std; int dblcmp(double x) { if(x > eps) return 1; else if(x < -eps) return -1; return 0; } LL search(LL n, LL x) { LL l = 0, r = n; LL mid; double sum, tp; int cx; while(l <= r) { mid = MID(l, r); sum = 0; tp = mid; cx = 0; for( ; cx < x && dblcmp(sum - n) == -1; cx++, sum += tp, tp *= mid); if(cx < x) { r = mid - 1; continue; } if(dblcmp(sum - n) == 0 || dblcmp(sum - n + 1) == 0) return mid; else if(dblcmp(sum - n) == -1) l = mid + 1; else r = mid - 1; } return -1; } int main() { //Read(); LL n, r, k, tmp; LL ar, ak; while(~scanf("%lld", &n)) { tmp = -1; for(r = 1; r <= 60; ++r) { k = search(n, r); if(k == -1) continue; if(r*k < tmp || tmp == -1) { tmp = r*k; ar = r; ak = k; } } printf("%lld %lld\n", ar, ak); } return 0; }
Oooooooooooooooooooooooorz