hdu4421 Bit Magic
2-SAT,也可以根据异或的关系用并查集直接把解求出来,然后判定是否满足与或非的限制。
还是2-SAT写起来爽……
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 505 int B[N][N] , n , K; int pre[N + N] , mcnt; struct edge { int x , next; }e[N * N * 16]; void addedge(int x , int y) { e[mcnt].x = y , e[mcnt].next = pre[x] , pre[x] = mcnt ++; } void build() { int i , j; memset(pre, -1 , sizeof(pre)); mcnt = 0; // + n == 1 , no n == 0 for (i = 0 ; i < n ; ++ i) { for (j = i + 1 ; j < n ; ++ j) { if (i % 2 == 0 && j % 2 == 0) { if (B[i][j] & (1 << K)) { addedge(i , i + n); addedge(j , j + n); addedge(i + n , j + n); addedge(j + n , i + n); } else { addedge(i + n , j); addedge(j + n , i); } } else if (i % 2 == 1 && j % 2 == 1) { if (B[i][j] & (1 << K)) { addedge(i , j + n); addedge(j , i + n); } else { addedge(i + n , i); addedge(j + n , j); addedge(i , j); addedge(j , i); } } else { if (B[i][j] & (1 << K)) { addedge(i , j + n); addedge(j , i + n); addedge(i + n , j); addedge(j + n , i); } else { addedge(i , j); addedge(j , i); addedge(i + n , j + n); addedge(j + n , i + n); } } } } } int DFN[N + N] , low[N + N] , bel[N + N] , ncnt , bcnt; stack<int> S; bool in[N + N]; bool tarjan(int x) { DFN[x] = low[x] = ++ ncnt; S.push(x) , in[x] = 1; for (int i = pre[x] ; ~i ; i = e[i].next) { int y = e[i].x; if (!DFN[y]) { tarjan(y); low[x] = min(low[x] , DFN[y]); } else if (in[y]) low[x] = min(low[x] , low[y]); } if (DFN[x] == low[x]) { ++ bcnt; int y; do { y = S.top() , S.pop(); in[y] = 0 , bel[y] = bcnt; }while (y != x); } } bool check() { memset(DFN , 0 , sizeof(DFN)); memset(low , 0 , sizeof(low)); ncnt = bcnt = 0; for (int i = 0 ; i < n + n ; ++ i) if (!DFN[i]) tarjan(i); for (int i = 0 ; i < n ; ++ i) if (bel[i] == bel[i + n]) return 0; return 1; } void work() { int i , j; for (i = 0 ; i < n ; ++ i) for (j = 0 ; j < n ; ++ j) scanf("%d",&B[i][j]); for (K = 0 ; K < 31 ; ++ K) { build(); if (!check()) break; } puts(K < 31 ? "NO" : "YES"); } int main() { while (~scanf("%d",&n)) work(); return 0; }
hdu4422 The Little Girl who Picks Mushrooms
题意只要理解了就不难了,答案最多只有1024,n<=3时结果肯定为1024,n=5时可以直接枚举,n=4时也可以枚举第5座山摘了多少然后和n=5一样处理
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 505 int n , a[N]; void work() { int i , j , k , l , sum = 0 , ans = 0, x; for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]) , sum += a[i]; if (n <= 3) { puts("1024"); return; } if (n == 4) { ++ n; for (a[n] = 0 ; a[n] <= 2012 ; ++ a[n]) { for (i = 1 ; i <= n ; ++ i) for (j = i + 1 ; j <= n ; ++ j) for (k = j + 1 ; k <= n ; ++ k) if ((a[i] + a[j] + a[k]) % 1024 == 0) { x = (sum - a[i] - a[j] - a[k] - 1) % 1024 + 1; ans = max(x , ans); } ++ sum; } printf("%d\n" , ans); return; } if (n == 5) { for (i = 1 ; i <= n ; ++ i) for (j = i + 1 ; j <= n ; ++ j) for (k = j + 1 ; k <= n ; ++ k) if ((a[i] + a[j] + a[k]) % 1024 == 0) { x = (sum - a[i] - a[j] - a[k] - 1) % 1024 + 1; ans = max(x , ans); } printf("%d\n" , ans); } } int main() { while (~scanf("%d",&n)) work(); return 0; }
hdu4424 Conquer a New Region
将边从大到小排序,这样访问每条边的时候就可以保证这条边就是所连接两个集合的瓶颈,就可以判断汇点在哪边的集合较优,用并查集维护。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 200005 int n , m , f[N] , s[N]; LL d[N]; pair<int , pair<int , int> > a[N]; int getf(int x) {return x == f[x] ? x : f[x] = getf(f[x]);} void work() { int i , x , y ; LL ans = 0 , sx , sy; for (i = 0 ; i < n - 1 ; ++ i) scanf("%d%d%d",&a[i].se.fi , &a[i].se.se , &a[i].fi); for (i = 1 ; i <= n ; ++ i) f[i] = i , s[i] = 1 , d[i] = 0; sort(a , a + n - 1 , greater< pair<int , pair<int , int> > >() ); for (i = 0 ; i + 1 < n ; ++ i) { x = getf(a[i].se.fi) , y = getf(a[i].se.se); sx = d[x] + (LL) s[y] * a[i].fi; sy = d[y] + (LL) s[x] * a[i].fi; if (sx > sy) f[y] = x , s[x] += s[y] , d[x] = sx; else f[x] = y , s[y] += s[x] , d[y] = sy; } for (i = 1 ; i <= n ; ++ i) if (getf(i) == i) break; cout << d[i] << endl; } int main() { while (~scanf("%d",&n)) work(); return 0; }
hdu4426 Palindromic Substring
manacher预处理之后就能利用hash统计出整个字符串有多少种回文串,同时统计字符串出现的次数,方法参考的
http://www.mzry1992.com/blog/miao/2012changchun-regional-g.html
统计出来以后对于每次询问只需要暴力计算排序即可
WA了N次的原因是K没有开longlong
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 200005 char str[N >> 1] , s[N]; int p[N] , n , m , val[27] , ca; ULL hash[N >> 1] , MAGIC = 67 , power[N >> 1]; LL K; int Q = 777777777 , p2[N >> 1] , ra[N >> 1]; struct contain { ULL h ; int l , t , pre; bool operator < (const contain& r) const{ return l > r.l;} }pl[N]; map< pair<ULL , int> , int> id; ULL get(int x , int y) { return hash[y] - hash[x - 1] * power[y - x + 1]; } int get2(int x , int y) { return (Q + ra[y] - (LL)ra[x - 1] * p2[y - x + 1] % Q) % Q; } pair<int , int> od[N]; void work() { int i , j , k , len = 1 , ans = 0; scanf("%d%d%s" , &n , &m , str); s[0] = '%'; for (i = 0 ; str[i] ; ++ i) s[len ++] = '#' , s[len ++] = str[i]; s[len ++] = '#';s[len] = 0; for (i = 1 ; i <= n ; ++ i) hash[i] = hash[i - 1] * MAGIC + (str[i - 1] - 'a' + 1); int iid = 0 , mx = 0; for (i = 0 ; i != len ; ++ i) { p[i] = mx > i ? min(p[iid + iid - i], mx - i) : 1; while (s[i + p[i]] == s[i - p[i]]) ++ p[i]; if (i + p[i] > mx) mx = i + p[i] , iid = i; } int sum = 0; ULL x , y; id.clear(); for (i = 2 ; i + 1 != len ; ++ i) { j = p[i] - (s[i] == '#'); while (j > 1) { x = get((i - j >> 1) + 1 , i >> 1); if (!(k = id[make_pair(x , j >> 1)])) { id[make_pair(x , j >> 1)] = ++ sum; pl[sum] = (contain) {x , j >> 1 , 1 , i >> 1}; } else { ++ pl[k].t; break; } j -= 2; } } //for (i = 1 ; i <= sum ; ++ i) // printf("%d\n" , pl[i].h2 , " \n"[i == sum]); sort(pl + 1 , pl + sum + 1); id.clear(); for (i = 1 ; i <= sum ; ++ i) id[make_pair(pl[i].h , pl[i].l)] = i; for (i = 1 ; i <= sum ; ++ i) { x = pl[i].h , j = pl[i].l; if (j > 1) { x -= power[j - 1] * (str[pl[i].pre - j] - 'a' + 1) , -- j; if (id.count(make_pair(x , j))) pl[id[make_pair(x , j)]].t += pl[i].t - 1; } } while (m --) { scanf("%I64d" , &K); for (i = 0 ; i < 26 ; ++ i) scanf("%d" , &val[i]); for (i = 1 ; i <= n ; ++ i) ra[i] = ((LL)ra[i - 1] * 26 % Q + (val[str[i - 1] - 'a'])) % Q ; for (i = 1 ; i <= sum ; ++ i) od[i] = make_pair(get2( pl[i].pre - pl[i].l + 1 , pl[i].pre) , pl[i].t); sort(od + 1 , od + sum + 1); for (i = 1 ; i <= sum ; ++ i) { K -= od[i].se; if (K <= 0) { printf("%d\n" , od[i].fi); break; } } } puts(""); } int main() { std::ios::sync_with_stdio(false); power[0] = p2[0] = 1; for (int i = 1 ; i <= 100000 ; ++ i) power[i] = power[i - 1] * MAGIC , p2[i] = (LL) p2[i - 1] * 26 % Q; int _; scanf("%d",&_); while (_--) work(); return 0; }
hdu4427 Math Magic
DP,集合中的每个数字都肯定M的约数,需要预处理出这些约数的LCM,不然会T……
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 1005 int n , m , K , Q = 1e9 + 7; int f[2][1001][100] , lcm[100][100]; int bel[N] , fal[N] , sum; void work() { int i , j , k , l , x; sum = 0 , memset(bel , 0 , sizeof(bel)); for (i = 1 ; i * i <= m ; ++ i) if (m % i == 0) { fal[++ sum] = i; if (m != i * i) fal[++ sum] = m / i; } sort(fal + 1 , fal + 1 + sum); for (i = 1 ; i <= sum ; ++ i) bel[fal[i]] = i; for (i = 1 ; i <= sum ; ++ i) for (j = 1 ; j <= sum ; ++ j) lcm[i][j] = fal[i] / __gcd(fal[i] , fal[j]) * fal[j]; memset(f , 0 , sizeof(f)); f[0][0][1] = 1; for (k = 0 ; k < K ; ++ k) { memset(f[!(k & 1)] , 0 , sizeof(f[k & 1])); for (i = 0 ; i <= n ; ++ i) for (j = 1 ; j <= sum ; ++ j) if (f[k & 1][i][j]) { for (l = 1 ; i + fal[l] <= n && l <= sum ; ++ l) { x = lcm[j][l]; f[!(k & 1)][i + fal[l]][bel[x]] += f[k & 1][i][j]; if (f[!(k & 1)][i + fal[l]][bel[x]] >= Q) f[!(k & 1)][i + fal[l]][bel[x]] -= Q; } } } printf("%d\n" , f[K & 1][n][bel[m]]); } int main() { std::ios::sync_with_stdio(false); while (cin >> n >> m >> K) work(); return 0; }
hdu4429 Split the Rectangle
根据矩形的分割顺序可以构建出一棵二叉树,然后要让两个矩形内的点在一个空矩形里面就意味着两个矩形的LCA代表的矩形要整个变空。
询问就转化成了询问两个叶子的LCA,返回LCA的子树的叶子数。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 2005 int n , Q , f[N] , d[N] , m , sum[N]; int xl , yl , xr , yr; struct rect { int x1 , x2 , y1 , y2 , id; }rec[N]; void work() { int i , j , x , y , ans; rec[m = 1] = (rect) {xl , xr , yl , yr , 1}; cin >> n >> Q; memset(f , 0 , sizeof(f)); memset(sum , 0 , sizeof(sum)); for (j = 1 ; j <= n ; ++ j) { cin >> xl >> yl >> xr >> yr; if (xl > xr) swap(xl , xr); if (yl > yr) swap(yl , yr); for (i = 1 ; i <= m ; ++ i) if (rec[i].id) { if (xl == xr) { if (yl == rec[i].y1 && yr == rec[i].y2 && xl >= rec[i].x1 && xr <= rec[i].x2) { f[++ m] = rec[i].id , d[m] = d[rec[i].id] + 1 , rec[m] = (rect) {rec[i].x1 , xl , rec[i].y1 , rec[i].y2 , m}; f[++ m] = rec[i].id , d[m] = d[rec[i].id] + 1 , rec[m] = (rect) {xl , rec[i].x2 , rec[i].y1 , rec[i].y2 , m}; rec[i].id = 0; break; } } if (yl == yr) { if (xl == rec[i].x1 && xr == rec[i].x2 && yl >= rec[i].y1 && yr <= rec[i].y2) { f[++ m] = rec[i].id , d[m] = d[rec[i].id] + 1 , rec[m] = (rect) {rec[i].x1 , rec[i].x2 , rec[i].y1 , yl , m}; f[++ m] = rec[i].id , d[m] = d[rec[i].id] + 1 , rec[m] = (rect) {rec[i].x1 , rec[i].x2 , yr , rec[i].y2 , m}; rec[i].id = 0; break; } } } } for (i = 1 ; i <= m ; ++ i) if (rec[i].id) { x = i; while (x) ++ sum[x] , x = f[x]; } while (Q --) { cin >> xl >> yl >> xr >> yr; for (i = 1 ; i <= m ; ++ i) if (rec[i].id) { if (xl >= rec[i].x1 && xl <= rec[i].x2 && yl >= rec[i].y1 && yl <= rec[i].y2) break; } x = i; for (i = 1 ; i <= m ; ++ i) if (rec[i].id) { if (xr >= rec[i].x1 && xr <= rec[i].x2 && yr >= rec[i].y1 && yr <= rec[i].y2) break; } y = i; if (d[x] > d[y]) swap(x , y); while (d[x] != d[y]) y = f[y] , ++ ans; while (x != y) y = f[y] , x = f[x] , ans += 2; //cout << ans << endl; cout << n + 2 - sum[x] << endl; } } int main() { std::ios::sync_with_stdio(false); while (cin >> xl >> yl >> xr >> yr) work(); return 0; }
hdu4430 Yukari's Birthday
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 200005 LL n; pair<LL , LL> ans; LL cal(int k , int r) { LL x = 1 , sum = 0; for (int i = 1 ; i <= r ; ++ i) x *= k , sum += x; return sum; } void work() { LL sum , x , y; int r , k , top , bot , m; ans = make_pair(n - 1 , 1); for (r = 2 ; r <= 39 ; ++ r) { top = 2 , bot = pow(n , 1.0 / r) + 2; while (top <= bot) { m = (top + bot) >> 1 , sum = cal(m , r); if (sum == n) { ans = min(ans , make_pair((LL)r * m , (LL)r)); break; } if (sum > n) bot = m - 1; else top = m + 1; } } -- n; for (r = 2 ; r <= 39 ; ++ r) { top = 2 , bot = pow(n , 1.0 / r) + 2; while (top <= bot) { m = (top + bot) >> 1 , sum = cal(m , r); if (sum == n) { ans = min(ans , make_pair((LL)r * m , (LL)r)); break; } if (sum > n) bot = m - 1; else top = m + 1; } } printf("%I64d %I64d\n" , ans.se , ans.fi / ans.se); } int main() { std::ios::sync_with_stdio(false); while (cin >> n) work(); return 0; }