EOJ 3329 dp
来源:互联网 发布:linux apr版本 编辑:程序博客网 时间:2024/06/05 17:46
题意:
题目链接:http://acm.ecnu.edu.cn/problem/3329/
中文题。但是题意有点迷,在计算子集个数时,对于同一个子集只计算一次,如{1,2,3,3}中存在两个{1,2,3},但是计算的时候只算一个{1,2,3}。
思路:
dp,需要点优化,因为这里数的范围只有3500~4500,所以可以存这些数字的个数,注意到这里异或产生的质数最多只到8191。
dp[i][j]表示到第i个出现的数字异或和为j的个数有多少,状态转移为:
dp[i][j] = dp[i-1][j] * x + dp[i-1][j^num[i]] * y;
这里x和y分别是第i个数字出现的个数中偶数的个数和奇数的个数;
最后需要滚动数组。
代码:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int MAXN = 1e5 + 10;const LL MOD = 1e9 + 7;bool prime[MAXN];void init() { for (int i = 2; i <= 8200; i++) prime[i] = true; for (int i = 2; i <= 8200; i++) { if (!prime[i]) continue; for (int j = i * 2; j <= 8200; j += i) prime[j] = false; }}int cnt[MAXN];LL dp[2][8200];int main() { //freopen("in.txt", "r", stdin); init(); int n, x; scanf("%d", &n); vector <int> vec; for (int i = 1; i <= n; i++) { scanf("%d", &x); cnt[x]++; } for (int i = 3500; i <= 4500; i++) { if (cnt[i] > 0) vec.push_back(i); } n = vec.size(); dp[0][0] = 1; for (int i = 1; i <= n; i++) { LL x1 = (cnt[vec[i - 1]] + 1) / 2, x2 = cnt[vec[i - 1]] / 2 + 1; for (int j = 0; j < 8192; j++) { dp[i % 2][j] = ((dp[(i - 1) % 2][j] * x2) % MOD + (dp[(i - 1) % 2][j ^ vec[i - 1]] * x1) % MOD) % MOD; } } LL ans = 0; for (int i = 2; i < 8192; i++) { if (prime[i]) ans = (ans + dp[n % 2][i]) % MOD; } printf("%I64d\n", ans); //check(n); return 0;}
阅读全文
0 0
- EOJ 3329 dp
- EOJ-3261 字典树 + dp
- eoj 3329 奇异收缩的剪影(异或性质的运用,简单dp)(存疑)
- EOJ
- EOJ
- EOJ
- EOJ 2857:编辑距离(DP)
- EOJ 3261 分词 dp+字典树
- EOJ 3261 字典树+dp 字典树模版
- EOJ 1051:(算法作业4-1)完全加括号的矩阵连乘积(DP)
- EOJ gauss
- EOJ 1255
- EOJ 1851
- EOJ 2096
- EOJ 2141
- EOJ 2562
- EOJ 1818
- EOJ----足球锦标赛
- .tar.bz2文件解压命令
- Composer安装Thinkphp5
- 将项目发布到Maven中央库
- Java之assert方法使用
- 最全Pycharm教程(40)——Pycharm扩展功能之捆绑插件TextMate
- EOJ 3329 dp
- C#中base64 bytes[] Stream之间的相互转换以及PDF转成图片
- 【leetcode】190. Reverse Bits(Python & C++)
- js 中方便调试 打印日志 -- 将json 和字符串互转
- 二维数组练习原创五子连珠
- 机器学习_miml多示例多标记算法
- [bzoj5039][线段树][lazy]序列维护
- 聚类算法之层次聚类与密度聚类
- hdu1394 Minimum Inversion Number(线段树单点修改+区间求和)