zoukankan      html  css  js  c++  java
  • Codeforces #564div2 E1(记忆化搜索)

    虽然不是正解但毕竟自己做出来了还是记下来吧~
    对每个人分别dfs得到其期望,某两维的组合情况有限所以Hash一下避免了MLE。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    using namespace std;
    
    const int maxn = 51, mod = 998244353;
    int n, m, like[maxn], w[maxn];
    int sum[2], cnt[2], val[maxn * maxn][maxn * maxn], dp[maxn][maxn << 1][5000][2];//in fact, 2500 is ok
    unordered_map<long long, int> mp;
    int hashcnt;
    
    int ksm(int a, int b) {
    	int res = 1;
    	for (; b; b >>= 1) {
    		if (b & 1)	res = 1LL * res * a % mod;
    		a = 1LL * a * a % mod;
    	}
    	return res;
    }
    
    int calc(int wi, int sum) {//wi / sum
    	if (val[wi][sum] != -1)	return val[wi][sum];
    	return val[wi][sum] = 1LL * wi * ksm(sum, mod - 2) % mod;	
    }
    
    int Hash(int x, int y) {//[suma][sumb] is MLE, so hash it
    	long long t = 10000LL * x + y;
    	return mp.count(t) ? mp[t] : mp[t] = hashcnt++;
    }
    
    int dfs(int depth, int wi, int suma, int sumb, int like) {
    	if (depth == m + 1) {
    		return wi;
    	}
    	int &x = dp[depth][wi][Hash(suma, sumb)][like];
    	if (x != -1)	return x;
    	int add = like ? 1 : -1, ts = 0;
    	//select this
    	if (wi > 0)	ts = (1LL * calc(wi, suma + sumb) * dfs(depth + 1, wi + add, suma + add, sumb, like) + ts) % mod;
    	//select one the same as it
    	if (suma > wi)	ts = (1LL * calc(suma - wi, suma + sumb) * dfs(depth + 1, wi, suma + add, sumb, like) + ts) % mod;
    	//select one from opposite
    	if (sumb > 0)	ts = (1LL * calc(sumb, suma + sumb) * dfs(depth + 1, wi, suma, sumb - add, like) + ts) % mod;
    	return x = ts;
    }
    
    int main() {
    	scanf("%d %d", &n, &m);
    	for (int i = 0; i < n; i++) {
    		scanf("%d", &like[i]);
    		cnt[like[i]]++;
    	}
    	for (int i = 0; i < n; i++) {
    		scanf("%d", &w[i]);
    		sum[like[i]] += w[i];//sum[0] sum[1]
    	}
    	memset(val, -1, sizeof val);
    	memset(dp, -1, sizeof dp);
    	for (int i = 0; i < n; i++) {
    		printf("%d
    ", dfs(1, w[i], sum[like[i]], sum[like[i] ^ 1], like[i]));
    	}
    }
    
  • 相关阅读:
    EF支持的注解
    c#数组去重复超级简单
    终于开通博客了。
    理解C#中参数
    一般处理程序中session问题
    小菜的面试所感
    为IOS生成opencv framework时遇到的2个问题
    纯真IP地址数据库qqwry.dat解析
    scala纯函数式编程-排序算法实现
    跳跃列表原理和实现
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10997451.html
Copyright © 2011-2022 走看看