题意:给定一堆2二进制砝码,给定一个物品,要求在天平两端加入物品和砝码使之平衡,求可能数。

思路:一开始想到了直接用数学原理,结果没证出来。做如下思考,此题需要用二进制:

(1)设物品重量为w,加入的砝码重量为x,另一边重量为y,便有w+x=y。

(2)另外,假如物品为100110,加入的砝码可以为000010,那么总和为101000,显然x与y不能有位数相同的1(因为每种砝码只有一个),因此便有x&y=0

依据这两点,可以知道此题的关键之处就在于如何分析w+x的进位情况。分析物品的第i位,比如为1,那么如果前面的一位没有进位,那么他便可以加上1或者不加;如果进位,那就肯定不能加1(因为加1以后与进位的1加上这一位的结果还是1,与x&y=0矛盾),所以对于每一位,它的进位与不进位情况需要分开判断。

DP思路:设f[i][0]表示判断到i位时它不进位的情况数,f[i][1]表示到i位时它进位的情况数,都是从低位到高位判断。

(1)先考虑f[i][0](不进位的情况)

  • i位为1,如果前面不进位,那么这一位只能加上0才满足不进位的情况;如果前面进位,那么无论如何不可能使这一位不进位,因此f[i][0]=f[i-1][0];
  • i位为0,如果前面不进位,那么这一位只能选择0(因为选择加1的话将会与x&y=0矛盾);如果前面进位,那么这一位也只能选择0才能使i位也不进位,因此有f[i][0]=f[i-1][0]+f[i-1][1];

(2)再考虑f[i][1](进位的情况)

  • i位为1,如果前面不进位,那么这一位只能选择1才能使i位进位;如果前面进位,那么只能选择0使之进位(如果选择1那么结果将会与x&y=0矛盾),因此f[i][1]=f[i-1][0]+f[i-1][1];
  • i位为0,如果前面不进位,那么这一位无论如何不可能进位;如果前面进位,那么只能选择1才能使i位进位,因此f[i][1]=f[i-1][1];

这样,DP方程就得到了

if(s[i] == ){
f[i][] = f[i-][];
f[i][] = f[i-][]+f[i-][];
}
else{
f[i][] = f[i-][]+f[i-][];
f[i][] = f[i-][];
}

注意:不得不说,这个题目挺不错的,此题中间结果可能会超出long long,因此需要分次数判断,因为这个点我WA了N次

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <memory>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
#include <stack>
using namespace std; #define CLR(x,y) memset(x,y,sizeof(x))
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
#define rep(i,x,y) for(i=x;i<y;++i) const int MAXN = 1100000; int t,n,m,d;
int s[MAXN];
int dp[MAXN][2]; void Solve()
{
char c; scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&d);
getchar();
CLR(s,0);
for(int i = m-1; i >= 0; --i){
scanf("%c",&c);
s[i] = c-'0';
}
if(s[0] == 0) {
dp[0][0] = 1;
dp[0][1] = 0;
}
else{
dp[0][0] = 1;
dp[0][1] = 1;
}
for(int i = 1; i < n; ++i){
if(s[i] == 1){
dp[i][0] = dp[i-1][0];
dp[i][1] = dp[i-1][0]+dp[i-1][1];
}
else{
dp[i][0] = dp[i-1][0]+dp[i-1][1];
dp[i][1] = dp[i-1][1];
}
if(dp[i][0]>=d) dp[i][0]-=d;
if(dp[i][1]>=d) dp[i][1]-=d;
}
cout<<(dp[n-1][0])<<endl;
}
} int main()
{
Solve();
return 0;
}

{POJ}{3971}{Scales}{O(N)动态规划}的更多相关文章

  1. POJ.3172 Scales (DFS)

    POJ.3172 Scales (DFS) 题意分析 一开始没看数据范围,上来直接01背包写的.RE后看数据范围吓死了.然后写了个2^1000的DFS,妥妥的T. 后来想到了预处理前缀和的方法.细节以 ...

  2. POJ 1163 The Triangle(简单动态规划)

    http://poj.org/problem?id=1163 The Triangle Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

  3. [POJ 1787]Charlie's Change (动态规划)

    题目链接:http://poj.org/problem?id=1787 题意:有4种货币分别是1元,5元,10元,20元.现在告诉你这四种货币分别有多少个,问你正好凑出P元钱最多可以用多少货币.每种货 ...

  4. POJ 1080 Human Gene Functions -- 动态规划(最长公共子序列)

    题目地址:http://poj.org/problem?id=1080 Description It is well known that a human gene can be considered ...

  5. POJ 1050 To the Max -- 动态规划

    题目地址:http://poj.org/problem?id=1050 Description Given a two-dimensional array of positive and negati ...

  6. POJ 1458 Common Subsequence (动态规划)

    题目传送门 POJ 1458 Description A subsequence of a given sequence is the given sequence with some element ...

  7. POJ - 1163 The Triangle 【动态规划】

    一.题目 The Triangle 二.分析 动态规划入门题. 状态转移方程$$DP[i][j] = A[i][j] + max(DP[i-1][j], DP[i][j])$$ 三.AC代码 1 #i ...

  8. [ACM_动态规划] POJ 1050 To the Max ( 动态规划 二维 最大连续和 最大子矩阵)

    Description Given a two-dimensional array of positive and negative integers, a sub-rectangle is any ...

  9. POJ 3172 Scales (01背包暴力)

    题意:给定 n 个数,保证下一个数比上一个数和前一个数之和大,然后给定一个背包,问你最多放多少容积. 析:应该是很明显的01背包,但是可惜的是,数组开不出来,那就得考虑暴力,因为数不多,才几十而已,要 ...

随机推荐

  1. PHP如何通过CURL上传文件

    PHP使用CURL上传文件只需发送一个POST请求就可以了,在请求中设置某个字段为需要上传的文件全路径,并且以“@”开头,然后使用CURL把该变量以POST方式发送到服务器,在服务端即可以从超级全局变 ...

  2. ios中图片拉伸用法

    - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCap ...

  3. TEX学习笔记

    整理在这里, 方便以后容易查找. 毕竟每个tex的模板有些不一样. Beamer: Latex beamer 学习总结 http://blog.sina.com.cn/s/blog_6cf921f30 ...

  4. 使用Visual Studio调试用户模式进程(Debugging a User-Mode Process Using Visual Studio)

    由于本人能力有限,翻译不足之处敬请谅解,欢迎批评指正:sunylat@163.com Visual Studio版本:Visual Studio 2015企业版,中文环境. MSDN原文:https: ...

  5. Blink Without Delay: 不使用 delay() 函数而使 LED 闪烁

    不使用 delay() 函数而使 LED 闪烁 有些时候你需要同时做两件事.例如,你可能希望在读取按键按下状态同时让LED闪烁. 在这种情况下,你不能使用 delay(),因为Arduino程序会在d ...

  6. C#播放声音的四种方法 +AxWindowsMediaPlayer的详细用法

    C#播放声音的四种方法 第一种是利用DirectX 1.安装了DirectX SDK(有9个DLL文件).这里我们只用到MicroSoft.DirectX.dll和 Microsoft.Directx ...

  7. 转:SAAS 测试

    基于SaaS云计算网络性能测试指标研究 来源:中国软件评测中心  作者:马子明  投稿时间:2011-04-02 1.基于SaaS的云计算 SaaS(Software as a Service,软件即 ...

  8. C#编辑图像文件EXIF信息

    private void setImageTag(string imgFile, string tagFile, string imgTag, string imgTitle) { ; if (Fil ...

  9. C语言atan2()函数:求y/x的反正切值

    头文件:#include <math.h> atan2() 函数用于求 y / x 的反正切值.其原型为:    double atan2(double y, double x); [参数 ...

  10. JS 学习(四)对象

    对象 在JS中,对象是数据(变量),拥有属性和方法. JS中所有事物都是对象:字符串.数字.数组.日期等. 对象是拥有属性和方法的特殊数据类型. 属性是与对象相关的值. 方法是能够在对象上执行的动作. ...