您的位置:首页 > 其它

SRM 508 DIV1 500pt(DP)

2014-12-09 18:23 330 查看
题目简述

给定一个大小为 n的序列(n<=10)R,要求你计算序列A0, A1, ..., AN-1的数量,要求A序列满足A0 + A1 + ... + AN-1 = A0 | A1 | ... | AN-1(0<=Ai<=R[i])

题解

把n个数看成二进制,如果要求n个数的和等于n个数的或值,那么对于n个数的每一位,最多只可能有一个1,因为超过一个一就会产生进位。

由于第i个数如果当前位放置的是0,但 R[i]的当前位是1,那么之后的位置上就可以随意放了,没有限制,所以我们可以用DP[i][j]表示在第i位,当前状态为j的符合要求的方案数有多少(j的二进制中1表示放置的数没有限制,不然就是有限制),用记忆化搜索很好实现~~

代码:

#define MOD 1000000009;
ll dp[65][1111];
vector<ll>r;
int n;
ll DP(int i, int mask)
{
if (i == -1) return 1;
ll &ret = dp[i][mask];
if(ret!=-1) return ret;
ret=0;
int next = mask;
for (int t = 0; t < n; t++)
if (r[t] & (1LL << i))
next |= (1 << t);
ret += DP(i - 1, next);
ret%=MOD;
for (int t = 0; t < n; t++)
if (mask & (1 << t))
{
ret += DP(i - 1, next);
ret %= MOD;
}
else if (r[t] & (1LL << i))
{
ret += DP(i - 1, next ^ (1 << t));
ret %= MOD;
}
return ret;
}
class YetAnotherORProblem
{
public:
int countSequences(vector<long long> R)
{
n = R.size();
r = R;
memset(dp, -1, sizeof(dp));
return DP(60, 0);
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: