zoukankan      html  css  js  c++  java
  • bzoj2616:SPOJ PERIODNI

    Pre

    调了好久好久。(QAQ)

    高高兴兴的打了一个(DP)数组的转移的程序,直接(T)掉,后来看了题解发现有优化。

    Solution

    状态转移有三个部分组成,一个是左右子树,一个是矩形。

    依次设置为(i,j,k),可以枚举,时间复杂度太高。

    新开一个数组,存下当前状态下的(i+j)的总答案,时间复杂度(O(n^2)),在枚举(k),状态转移,时间复杂度(O(n^2))

    Code

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std; 
    
    const int mod = 1000000007, N = 550, M = 1000000 + 5;
    int a[N], n, K;
    int stk[N], top;
    int ch[N][2], fa[N], sz[N];
    ll dp[N][N], fac[M], f[N][N];
    inline ll Pow (ll u, ll v) {
    	ll tot = 1, base = u;
    	while (v) {
    		if (v % 2 == 1) {
    			tot = tot * base % mod;
    		}
    		base = base * base % mod;
    		v /= 2;
    	}
    	return tot;
    }
    inline ll C (ll u, ll v) {
    	return fac[u] * Pow (fac[v], mod - 2) % mod * Pow (fac[u - v], mod - 2) % mod;
    }
    inline void dfs (int p, int v) {
    	sz[p]++;
    	if (ch[p][0]) {dfs (ch[p][0], a[p]);sz[p] += sz[ch[p][0]];}
    	if (ch[p][1]) {dfs (ch[p][1], a[p]);sz[p] += sz[ch[p][1]];}
    	for (int i = 0; i <= K; ++i) {
    		for (int j = 0; j <= K; ++j) {
    			if (i + j > K) {break;}
    			f[p][i + j] = (f[p][i + j] + dp[ch[p][0]][i] * dp[ch[p][1]][j] % mod) % mod;
    		}
    	}
    	for (int i = 0; i <= K; ++i) {
    		if (i > a[p] - v) {break;}
    		for (int j = 0; j <= K; ++j) {
    			if (i + j > K || i + j > sz[p]) {break;}
    			dp[p][i + j] = (dp[p][i + j] + f[p][j] * fac[a[p] - v] % mod * Pow (fac[a[p] - v - i], mod - 2) % mod * C (sz[p] - j, i) % mod) % mod;
    		}
    	}
    }
    int main () {
    	scanf ("%d%d", &n, &K);
    	fac[0] = 1; f[0][0] = 1; dp[0][0] = 1;
    	for (int i = 1; i <= M - 5; ++i) {
    		fac[i] = fac[i - 1] * i % mod;
    	}
    	for (int i = 1; i <= n; ++i) {
    		scanf ("%d", &a[i]);
    		while (top > 0 && a[stk[top]] > a[i]) {ch[i][0] = stk[top], top--;}
    		if (ch[fa[ch[i][0]]][0] == ch[i][0]) {ch[fa[ch[i][0]]][0] = 0;}
    		else {ch[fa[ch[i][0]]][1] = 0;}
    		fa[ch[i][0]] = i;
    		fa[i] = stk[top];
    		if (fa[i]) {ch[fa[i]][1] = i;}
    		stk[++top] = i;
    	}
    	int rt = 0;
    	for (int i = 1; i <= n; ++i) {if (!fa[i]) {rt = i;break;}}
    	dfs (rt, 0);
    	printf ("%lld
    ", dp[rt][K] % mod);
    	return 0;
    }
    

    Conclusion

    这个优化方法有意思。

  • 相关阅读:
    欢迎使用CSDN-markdown编辑器(这个只能看到一次保存一下)
    从Paxos到Zookeeper 分布式一致性原理与实践读书心得
    用java以正确的姿势刷CSP
    注意当cin.getline、和cin 合用的时候
    C++ 虚基类的定义、功能、规定
    python核心高级学习总结5--------python实现线程
    python核心高级学习总结4-------python实现进程通信
    linux下的bash shell
    多线程
    进程
  • 原文地址:https://www.cnblogs.com/ChiTongZ/p/11224383.html
Copyright © 2011-2022 走看看