• NEERC训练实录


    听说这里可以做一些idea比较好的题..

    那就做做吧

    2017-2018 ACM-ICPC, NEERC, Northern Subregional Contest

    A. Auxiliary Project

    有$7$就要$7$

    余$1$就少一个$7$多一个$4$,余$2$就多一个$1$

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    int n;
    int main() {
    	freopen("auxiliary.in", "r", stdin);
    	freopen("auxiliary.out", "w", stdout);
    	int i, j, k;
    	scanf("%d", &n);
    	if(n%3 == 0) printf("%d
    ", n/3*7);
    	else if(n%3 == 1) printf("%d
    ", (n/3-1)*7+4);
    	else printf("%d
    ", n/3*7+1);
    	return 0;
    }
    

    B. Boolean Satis ability

    好像很模拟??

    C. Consonant Fencity

    $2^17$枚举所有情况再算答案

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    const int Maxn = 1000010;
    char s[Maxn];
    int n;
    bool v[26];
    int num[26], l;
    int mp[26][26];
    int main() {
    	freopen("consonant.in", "r", stdin);
    	freopen("consonant.out", "w", stdout);
    	int i, j, k;
    	scanf("%s", s+1);
    	n = strlen(s+1);
    	v['a'-'a'] = v['e'-'a'] = v['i'-'a'] = v['o'-'a'] = v['u'-'a'] = v['w'-'a'] = v['y'-'a'] = true;
    	l = 0;
    	for(i = 1; i < 26; i++) if(!v[i]) num[i] = l++;
    	for(i = 2; i <= n; i++){
    		if(!v[s[i]-'a'] && !v[s[i-1]-'a']) mp[num[s[i]-'a']][num[s[i-1]-'a']]++;
    	}
    	int ans = 0, res = 0;
    	for(i = 1; i < 1<<l; i++){
    		int ret = 0;
    		for(j = 0; j < l; j++){
    			for(k = 0; k < l; k++){
    				if((i&(1<<j) && !(i&(1<<k))) || (!(i&(1<<j)) && i&(1<<k))) ret += mp[j][k];
    			}
    		}
    		if(ret > ans) ans = ret, res = i;
    	}
    	for(i = 1; i <= n; i++){
    		if(res&(1<<num[s[i]-'a'])) s[i] += 'A'-'a';
    		printf("%c", s[i]);
    	}
    	return 0;
    }
    

    *D. Dividing Marbles

    nike0good的blog,有空研究

    E. Equal Numbers

    一种是把它乘到它的一个存在的倍数,一种是把它乘到lcm

    分开处理这两种情况即可

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    const int Maxn = 1000010;
    int sum[Maxn], n;
    int a[Maxn], al, b[Maxn], bl;
    int f[Maxn];
    int _min(int x, int y) { return x < y ? x : y; }
    int main() {
    	freopen("equal.in", "r", stdin);
    	freopen("equal.out", "w", stdout);
    	int i, j, k;
    	scanf("%d", &n);
    	for(i = 1; i <= n; i++){
    		int x;
    		scanf("%d", &x);
    		sum[x]++;
    	}
    	int ss = 0;
    	for(i = 1; i <= 1000000; i++){
    		if(sum[i] > 0){
    			bool bk = false;
    			for(j = i+i; j <= 1000000; j += i){
    				if(sum[j] > 0){ bk = true; break; }
    			}
    			if(bk == true) a[++al] = sum[i];
    			b[++bl] = sum[i];
    			ss++;
    		}
    	}
    	memset(f, 63, sizeof(f)); f[0] = ss;
    	sort(a+1, a+al+1);
    	int su = 0;
    	for(i = 1; i <= al; i++){
    		su += a[i];
    		f[su] = _min(f[su], ss-i);
    	}
    	sort(b+1, b+bl+1);
    	su = 0;
    	for(i = 1; i <= bl; i++){
    		su += b[i];
    		f[su] = _min(f[su], ss-i+1);
    	}
    	for(i = 0; i <= n; i++){
    		if(i) f[i] = _min(f[i], f[i-1]);
    		printf("%d%c", f[i], i==n?'
    ':' ');
    	}
    	return 0;
    }
    

    *F. Fygon 2.0

    留坑

    *G. Grand Test

    dfs,用反祖边覆盖树边,如果一条树边被覆盖了两次,把这两条反祖边拿出来

    然后找度数为$3$的两个点,一定存在三条路径

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    const int Maxn = 100010;
    struct node {
    	int x, y, next;
    }a[Maxn<<1]; int first[Maxn], len;
    void ins(int x, int y) {
    	len++;
    	a[len].x = x; a[len].y = y;
    	a[len].next = first[x]; first[x] = len;
    }
    int n, m;
    int fa[Maxn], bo[Maxn]; bool bk, insta[Maxn];
    int dfn[Maxn], id;
    int ansk1, ansk2, ansx, ansy;
    void dfs(int x) {
    	if(!bk) return;
    	dfn[x] = ++id; insta[x] = true;
    	for(int k = first[x]; k && bk; k = a[k].next){
    		int y = a[k].y;
    		if(y == fa[x]) continue;
    		if(!dfn[y]){
    			fa[y] = x; bo[y] = 0;
    			dfs(y);
    		} else if(insta[y]){
    			int p = x;
    			while(p != y){
    				if(bo[p]){
    					bk = false;
    					ansk1 = bo[p];
    					ansk2 = k;
    					break;
    				}
    				bo[p] = k;
    				p = fa[p];
    			}
    		}
    	}
    	insta[x] = false;
    }
    vector <int> vec[Maxn];
    queue <int> q;
    int pre[Maxn], ans[Maxn], ansl;
    int main() {
    	freopen("grand.in", "r", stdin);
    	freopen("grand.out", "w", stdout);
    	int i, j, k;
    	int T;
    	scanf("%d", &T);
    	while(T--){
    		scanf("%d%d", &n, &m);
    		len = 0; for(i = 1; i <= n; i++) first[i] = 0;
    		for(i = 1; i <= m; i++){
    			int x, y;
    			scanf("%d%d", &x, &y);
    			ins(x, y); ins(y, x);
    		}
    		for(i = 1; i <= n; i++) dfn[i] = 0; id = 0;
    		bk = true;
    		for(i = 1; i <= n && bk; i++) if(!dfn[i]) fa[i] = 0, dfs(i);
    		if(bk == true){ printf("-1
    "); continue; }
    		for(i = 1; i <= n; i++) vec[i].clear();
    		vec[a[ansk1].x].push_back(a[ansk1].y); vec[a[ansk1].y].push_back(a[ansk1].x);
    		vec[a[ansk2].x].push_back(a[ansk2].y); vec[a[ansk2].y].push_back(a[ansk2].x);
    		int p = a[ansk1].x;
    		while(p != a[ansk1].y){
    			vec[p].push_back(fa[p]); vec[fa[p]].push_back(p);
    			p = fa[p];
    		}
    		p = a[ansk2].x;
    		while(p != a[ansk2].y){
    			if(bo[p] != ansk1) vec[p].push_back(fa[p]), vec[fa[p]].push_back(p);
    			p = fa[p];
    		}
    		ansx = ansy = 0;
    		for(i = 1; i <= n; i++){
    			if(vec[i].size() == 3){
    				if(!ansx) ansx = i;
    				else { ansy = i; break; }
    			}
    		}
    		for(i = 1; i <= n; i++) pre[i] = -1;
    		printf("%d %d
    ", ansx, ansy);
    		pre[ansx] = 0;
    		q.push(ansx);
    		while(!q.empty()){
    			int x = q.front(); q.pop();
    			for(i = 0; i < vec[x].size(); i++){
    				int y = vec[x][i];
    				if(pre[y] == -1){
    					if(y == ansy){
    						ansl = 0; ans[++ansl] = ansy;
    						for(j = x; j; j = pre[j]) ans[++ansl] = j;
    						printf("%d ", ansl);
    						for(j = ansl; j >= 1; j--) printf("%d%c", ans[j], j==1?'
    ':' ');
    						continue;
    					}
    					pre[y] = x;
    					q.push(y);
    				}
    			}
    		}
    	}
    	return 0;
    }
    

    *H. Hidden Supervisors

    对于一棵树总有一种答案最大的方案使得所有不选的点都在叶子节点上

    dp根选与不选的最大匹配,发现$f_{i,1}-f_{i,0}leq 1$

    如果$f_{i,1}=f_{i,0}+1$,让根匹配并不会比让根不匹配差,那么直接连到$1$就行了

    其他的按照未匹配叶子节点的大小合并就行了

    另外只有单独一个点的要特殊考虑

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    const int Maxn = 100010;
    const int inf = 0x7fffffff;
    vector <int> vec[Maxn];
    int fa[Maxn], n;
    int f[Maxn][2], num[Maxn], size[Maxn];
    void dfs(int x) {
    	size[x] = 1;
    	if(vec[x].size() == 0) return;
    	int ret1 = -inf; f[x][0] = 0;
    	for(int i = 0; i < vec[x].size(); i++){
    		int y = vec[x][i];
    		dfs(y);
    		size[x] += size[y];
    		if(!vec[y].size()){
    			if(0 > ret1) ret1 = 0, num[x] = y;
    		} else {
    			f[x][0] += f[y][1];
    			if(f[y][0]-f[y][1] > ret1) ret1 = f[y][0]-f[y][1], num[x] = y;
    		}
    	}
    	f[x][1] = f[x][0]+ret1+1;
    }
    queue <int> q, qu;
    void dfs2(int x) {
    	for(int i = 0; i < vec[x].size(); i++){
    		int y = vec[x][i];
    		if(y == num[x]) continue;
    		if(!vec[y].size()) q.push(y);
    		else dfs2(y);
    	}
    	for(int i = 0; i < vec[num[x]].size(); i++){
    		int y = vec[num[x]][i];
    		if(!vec[y].size()) q.push(y);
    		else dfs2(y);
    	}
    }
    struct lnode {
    	int x, p;
    	lnode (int x = 0, int p = 0) : x(x), p(p) {}
    	bool operator<(const lnode &A) const { return p > A.p; }
    }list[Maxn]; int l;
    int main() {
    	freopen("hidden.in", "r", stdin);
    	freopen("hidden.out", "w", stdout);
    	int i, j, k;
    	scanf("%d", &n);
    	for(i = 2; i <= n; i++){
    		scanf("%d", &fa[i]);
    		if(fa[i]) vec[fa[i]].push_back(i);
    	}
    	for(i = 1; i <= n; i++){
    		if(!fa[i]) dfs(i);
    	}
    	int ans = 0;
    	if(vec[1].size() == 0) q.push(1);
    	else {
    		ans += f[1][1];
    		dfs2(1);
    	}
    	for(i = 2; i <= n; i++){
    		if(!fa[i]){
    			if(!vec[i].size()) qu.push(i);
    			else if(f[i][0] < f[i][1]) ans += f[i][1], fa[i] = 1, dfs2(i);
    			else list[++l] = lnode(i, size[i]-2*f[i][0]-1);
    		}
    	}
    	sort(list+1, list+l+1);
    	for(i = 1; i <= l; i++){
    		if(q.empty() && !qu.empty()){
    			int x = qu.front();
    			fa[x] = 1;
    			q.push(x); qu.pop();
    		}
    		if(!q.empty()){
    			int x = q.front(); q.pop();
    			fa[list[i].x] = x; ans++;
    			ans += f[list[i].x][0];
    			for(j = 0; j < vec[list[i].x].size(); j++){
    				int y = vec[list[i].x][j];
    				if(!vec[y].size()) q.push(y);
    				else dfs2(y);
    			}
    		} else {
    			fa[list[i].x] = 1;
    			ans += f[list[i].x][1];
    			dfs2(list[i].x);
    		}
    	}
    	while(!q.empty() && !qu.empty()){
    		int x = q.front(), y = qu.front(); q.pop(); qu.pop();
    		fa[y] = x; ans++;
    	}
    	while(!qu.empty()){
    		int x = qu.front(); qu.pop();
    		fa[x] = 1;
    		if(!qu.empty()){
    			int y = qu.front(); qu.pop();
    			fa[y] = x; ans++;
    		}
    	}
    	printf("%d
    ", ans);
    	for(i = 2; i <= n; i++) printf("%d%c", fa[i], i==n?'
    ':' ');
    }
    

    I. Intelligence in Perpendicularia

    就是总长度-在外面能看到的,扫描线+线段树就行了..

    *J. Joker

    留坑

    K. Kotlin Island

    枚举行列分多少块即可

    L. Little Difference

    问题就是要求$a^x+(a+1)^y=n$的方案数

    枚举$x$和$y$二分求$a$即可

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #define LL long long
    using namespace std;
    const LL sx = 1e18+100;
    LL n;
    struct lnode {
    	LL x, i, j;
    	lnode (LL x = 0, LL i = 0, LL j = 0) : x(x), i(i), j(j) {}
    }list[1000010]; LL l;
    LL mul(LL x, LL y) {
    	if(x > sx/y) return sx;
    	x *= y;
    	if(x > sx) return sx;
    	return x;
    }
    LL qpow(LL x, LL k) {
    	LL ret = 1;
    	while(k){
    		if(k&1) ret = mul(ret, x);
    		x = mul(x, x);
    		k >>= 1;
    	}
    	return ret;
    }
    bool check(LL x, LL i, LL j) {
    	return mul(qpow(x, i), qpow(x+1, j)) <= n;
    }
    int main() {
    	freopen("little.in", "r", stdin);
    	freopen("little.out", "w", stdout);
    	LL i, j, k;
    	scanf("%I64d", &n);
    	if((n&(-n)) == n){ printf("-1
    "); return 0; }
    	for(i = 0; i <= 59; i++){
    		LL p, o;
    		if(p = qpow(2, i) > n) break;
    		for(j = 1; j <= 31; j++){
    			if(mul(p, qpow(3, j)) > n) break;
    			LL L = 2, R = n, ret;
    			while(L <= R){
    				LL mid = L+R>>1;
    				if(check(mid, i, j)) ret = mid, L = mid+1;
    				else R = mid-1;
    			}
    			if(mul(qpow(ret, i), qpow(ret+1, j)) == n) list[++l] = lnode(ret, i, j);
    		}
    	}
    	printf("%I64d
    ", l);
    	for(i = 1; i <= l; i++){
    		printf("%I64d", list[i].i+list[i].j);
    		while(list[i].i--) printf(" %I64d", list[i].x);
    		while(list[i].j--) printf(" %I64d", list[i].x+1);
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    每日总结
    每日总结
    每日总结
    每日总结
    每日总结
    每日总结
    每日博客
    每日博客
    结对作业之全国疫情统计可视化地图
    每日博客
  • 原文地址:https://www.cnblogs.com/darklove/p/8118221.html
Copyright © 2020-2023  润新知