zoukankan      html  css  js  c++  java
  • [Arc102B]All Your Paths are Different Lengths_构造_二进制拆分

    All Your Paths are Different Lengths

    题目链接https://atcoder.jp/contests/arc102/tasks/arc102_b


    题解

    构造题有技巧,如果题目中要求了20和60,那就从这里入手好了。

    发现没法入手因为太平凡了....

    但是,他要求了每种值只出现了一次,容易联想到弄出来$log$个$2$的幂次。

    诶?想到这里发现,$20$好像差不多就是$log$大小。

    我们就放$20$个点,第$i$个点指向第$i + 1$个点两条边,$2^{i - 1}$和$0$。

    发现不能放20个因为有可能爆,那就放恰好$log$个就好。

    接着处理剩下的部分。

    其实就是想数位$dp$一样,处理$L$的每个$1$,把当前的$1$变成$0$然后加上前面的所有$1$,看看后面还能有多少连上就好。

    诶呀说不明白,看代码吧。

    代码

    #include <bits/stdc++.h>
    
    #define N 1000010 
    
    using namespace std;
    
    int Log[N];
    
    char *p1, *p2, buf[100000];
    
    #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
    
    int rd() {
    	int x = 0, f = 1;
    	char c = nc();
    	while (c < 48) {
    		if (c == '-')
    			f = -1;
    		c = nc();
    	}
    	while (c > 47) {
    		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
    	}
    	return x * f;
    }
    
    int bin[21];
    
    int a[20];
    
    struct Node {
    	int x, y, z;
    }e[100];
    
    int main() {
    	int n = rd();
    	n -- ;
    	bin[0] = 1;
    	for (int i = 1; i <= 20; i ++ ) {
    		bin[i] = bin[i - 1] << 1;
    	}
    	int k = 0;
    	int m = n;
    	bool flag = false;
    	while (m) {
    		k ++ ;
    		if (m % 2 == 0) {
    			flag = true;
    		}
    		m /= 2;
    	}
    	int tot = 0;
    	if (!flag) {
    		cout << k + 1 << ' ' ;
    		for (int i = 1; i <= k; i ++ ) {
    			// i -> i + 1
    			tot ++ ;
    			e[tot].x = i, e[tot].y = i + 1, e[tot].z = bin[i - 1];
    			tot ++ ;
    			e[tot].x = i, e[tot].y = i + 1, e[tot].z = 0;
    		}
    		cout << tot << endl ;
    		for (int i = 1; i <= tot; i ++ ) {
    			printf("%d %d %d
    ", e[i].x, e[i].y, e[i].z);
    		}
    		return 0;
    	}
    	// puts("Fuck");
    	cout << k << ' ' ;
    	for (int i = 1; i < k; i ++ ) {
    		tot ++ ;
    		e[tot].x = i, e[tot].y = i + 1, e[tot].z = bin[k - i - 1];
    		tot ++ ;
    		e[tot].x = i, e[tot].y = i + 1, e[tot].z = 0;
    	}
    	int cnt = 0;
    	for (int i = 0; i <= 20; i ++ ) {
    		if (n & bin[i]) {
    			a[ ++ cnt] = i;
    		}
    	}
    	int pre = bin[a[cnt]];
    	for (int i = cnt - 1; i; i -- ) {
    		tot ++ ;
    		e[tot].x = 1, e[tot].y = k - a[i], e[tot].z = pre;
    		pre += bin[a[i]];
    	}
    	tot ++ ;
    	e[tot].x = 1, e[tot].y = k, e[tot].z = n;
    	cout << tot << endl ;
    	for (int i = 1; i <= tot; i ++ ) {
    		printf("%d %d %d
    ", e[i].x, e[i].y, e[i].z);
    	}
    	return 0;
    }
    

    小结:Atcoder全是构造世人皆知.....这个因为都只出现一次,很容易想到二进制。然后数位dp就好了。

  • 相关阅读:
    「AHOI / HNOI2017」单旋
    【CQOI2012】局部极小值
    【CQOI2011】放棋子
    【gdoi2018 day2】第二题 滑稽子图
    【JSOI2018】潜入行动
    在vue中获取不到canvas对象? 两种解决办法。
    数据可视化echart
    在vue中使用高德地图开发,以及AMap的引入?
    mac 常使用的一些小技巧
    form编码方式application/x-www-form-urlencoded和multipart/form-data的区别?
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11455639.html
Copyright © 2011-2022 走看看