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

    这个优化方法有意思。

  • 相关阅读:
    173. Binary Search Tree Iterator
    199. Binary Tree Right Side View
    230. Kth Smallest Element in a BST
    236. Lowest Common Ancestor of a Binary Tree
    337. House Robber III
    449. Serialize and Deserialize BST
    508. Most Frequent Subtree Sum
    513. Find Bottom Left Tree Value
    129. Sum Root to Leaf Numbers
    652. Find Duplicate Subtrees
  • 原文地址:https://www.cnblogs.com/ChiTongZ/p/11224383.html
Copyright © 2011-2022 走看看