zoukankan      html  css  js  c++  java
  • JZOJ 4532. 【清华夏令营2016模拟5.31】图样(动态规划)

    Description:

    小火车励志成为一名辣鸡出题人,但是要成为一名辣鸡出题人,代码必须跑得比谁都快,这样就能把他们都卡常数了!为了锻炼自己,他找到了一位长者——乐滋滋,乐滋滋说:“你啊,tooyoung!西方的哪一个国家我没有去过?”小火车坐在高高的骨灰旁边,听长者讲那西方的事情。
    西方有n个国家,长者决定向西方的每个国家普及人生经验,但首先要让他们互通火车,第i个国家有一个权值Ai,修建连接第i个国家到第j个国家的铁路,需要付出Ai xor Aj(xor表示按位异或)的代价,长者希望代价总和尽量小(也就是选择一个最小生成树)。
    但是在长者以前,没人去过西方,所以不知道每个国家的权值。但是我们知道每个国家的权值都是一个在0到2^m-1之间的随机整数,长者希望知道他所需要付出的代价的期望。
    当然,答案是一个有理分数,为了避免精度误差长者需要你输出这个分数在模258280327(2*317+1,一个质数)意义下的值(如果不存在则输出-1)。

    https://gmoj.net/senior/#main/show/4532

    题解:

    考虑知道每个点的点权怎么求最小生成树的权值和:

    建出trie,对于trie的每个节点,如果它既有0儿子,又有1儿子,那么这两棵子树分别联通后,要找一条最小的边把它们连起来。

    于是我们可以枚举这个节点的深度,再枚举它的左子树和右子树的大小,问题转换为:

    (x)(y)(k)位二进制数,求它们之间的异或最小值。

    这个可以dp,设(f[x][y][k][u])(x,y,k)意义如上,(u)表示最小值(ge u)的方案数。

    枚举下一位怎么分开的,讨论下一位是0还是1,有点细节。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 258280327;
    
    ll ksm(ll x, ll y) {
    	ll s = 1;
    	for(; y; y /= 2, x = x * x % mo)
    		if(y & 1) s = s * x % mo;
    	return s;
    }
    
    const int N = 55;
    
    const int M = 260;
    
    int n, m;
    
    ll c[M][M];
    
    ll f[N][N][9][M];
    
    int a2[9];
    
    ll b[N];
    
    void build(int n) {
    	fo(i, 0, n) {
    		c[i][0] = 1;
    		fo(j, 1, i) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
    	}
    }
    
    int main() {
    	build(256);
    	a2[0] = 1; fo(i, 1, 8) a2[i] = a2[i - 1] * 2;
    	scanf("%d %d", &n, &m);
    	fo(i, 0, n) fo(j, 0, n) fo(k, 0, m) if(!i || !j || !k) {
    		ll s = 1;
    		fo(u, 1, i + j) s = s * a2[k] % mo;
    		ff(u, 0, a2[k]) f[i][j][k][u] = s;
    	}
    	fo(i, 1, n) fo(j, 1, n - i) fo(k, 1, m) {
    		fo(ni, 0, i) fo(nj, 0, j) {
    			int t = a2[k - 1];
    			if((ni && nj) || ((i - ni) && (j - nj))) {
    				t = 0;
    			}
    			ll xs = c[i][ni] * c[j][nj] % mo;
    			ff(u, 0, a2[k - 1]) {
    				if(t == 0) {
    					f[i][j][k][u + t] = (f[i][j][k][u + t] + f[ni][nj][k - 1][u] * f[i - ni][j - nj][k - 1][u] % mo * xs) % mo;
    				} else {
    					f[i][j][k][u + t] = (f[i][j][k][u + t] + f[ni][j - nj][k - 1][u] * f[i - ni][nj][k - 1][u] % mo * xs) % mo;
    				}
    			}
    		}
    		ll s = f[i][j][k][a2[k - 1]];
    		ff(u, 0, a2[k - 1]) f[i][j][k][u] = (f[i][j][k][u] + s) % mo;
    	}
    	ll ans = 0;
    	fo(i, 1, m) {
    		b[0] = 1;
    		b[1] = a2[m] - a2[i];
    		fo(j, 2, n) b[j] = b[j - 1] * b[1] % mo;
    		fo(j, 1, n) fo(k, 1, n - j) {
    			ll xs = c[n][j] * c[n - j][k] % mo * a2[m - i] % mo * b[n - j - k] % mo;
    			ll xs2 = 1;
    			fo(u, 1, j + k) xs2 = xs2 * a2[i - 1] % mo;
    			ans = (ans + xs * a2[i - 1] % mo * xs2) % mo;
    			ll s = 0;
    			ff(u, 1, a2[i - 1]) s = (s + f[j][k][i - 1][u]) % mo;
    			ans = (ans + xs * s) % mo;
    		}
    	}
    	ll v = ksm(a2[m], n);
    	pp("%lld
    ", ans * ksm(v, mo - 2) % mo);
    }
    
  • 相关阅读:
    离鞘剑(四)
    Node.js 蚕食计划(四)—— Express + SQL Server 搭建电影网站
    离鞘剑(三)
    python数据类型(第三弹)
    python数据类型(第二弹)
    python数据类型(第一弹)
    开发工具的安装与使用(总结篇)
    开发工具的安装与使用(第四弹)
    PriorityQueue和PriorityBlockingQueue
    一文弄懂java中的Queue家族
  • 原文地址:https://www.cnblogs.com/coldchair/p/12938173.html
Copyright © 2011-2022 走看看