题意:给定一堆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. dotNet下的一套解决方案

    很久没在博客园写文章了,打算把一直由自己一个人写的一整套系统开放出来,今天先放一些截图及可以演示的地址! 这套系统包含数据层(HB.Data).计划任务(HB.PlanTask).日志系统(HB.Lo ...

  2. linux中service *** start与直接运行/usr/bin/***的区别

    在linux想要运行启动一个服务有两种方法: 1,运行/etc/init.d/目录下的shell脚本,还可以有快捷方式,service *** start/ stop/restart /status, ...

  3. stdcall, cdecl, pascal 区别(转载)

    转载自:http://www.cnblogs.com/lidabo/archive/2012/11/21/2781484.html stdcall, cdecl, pascal 区别 这三个参数都是告 ...

  4. SparkStreaming(源码阅读十二)

    要完整去学习spark源码是一件非常不容易的事情,但是咱可以积少成多嘛~那么,Spark Streaming是怎么搞的呢? 本质上,SparkStreaming接收实时输入数据流并将它们按批次划分,然 ...

  5. OAF_文件系列7_实现OAF处理Excel的JXL包介绍(概念)

    20150714 Created By BaoXinjian

  6. 感知器、逻辑回归和SVM的求解

    这篇文章将介绍感知器.逻辑回归的求解和SVM的部分求解,包含部分的证明.本文章涉及的一些基础知识,已经在<梯度下降.牛顿法和拉格朗日对偶性>中指出,而这里要解决的问题,来自<从感知器 ...

  7. Linux下lampp详解 (转)

    重要文件解释: ProFTPD:一个Unix平台上或是类Unix平台上(如Linux, FreeBSD等)的FTP服务器程序,它是在自由软件基金会的版权声明(GPL)下开发.发布的免费软件,可以随意修 ...

  8. jQuery MiniUI开发系列之:Ajax处理超时、服务端错误

    MiniUI所有组件的ajax交互,均使用标准.成熟的jQuery.ajax. 依赖于jquery ajax组件的完善性,我们可以拦截住每一次ajax请求处理. 比如,拦截ajax返回数据前,判断返回 ...

  9. Spark SQL Example

     Spark SQL Example This example demonstrates how to use sqlContext.sql to create and load a table ...

  10. 【摘】crontab 各时间含义

    HELL=/bin/bash <==使用哪種 shell 介面 PATH=/sbin:/bin:/usr/sbin:/usr/bin <==執行檔搜尋路徑 MAILTO=root < ...