ZOJ 2042 Divisibility (DP)
Divisibility
Time Limit: 2 Seconds Memory Limit:65536 KB
Consider an arbitrary sequence of integers. One can place + or - operators between integers in the sequence, thus deriving different arithmetical expressions that evaluate to different values. Let us, for example, take the sequence: 17, 5, -21, 15. There are eight possible expressions:
17 + 5 + -21 + 15 = 16
17 + 5 + -21 - 15 = -14
17 + 5 - -21 + 15 = 58
17 + 5 - -21 - 15 = 28
17 - 5 + -21 + 15 = 6
17 - 5 + -21 - 15 = -24
17 - 5 - -21 + 15 = 48
17 - 5 - -21 - 15 = 18
We call the sequence of integers divisible by K if + or - operators can be placed between integers in the sequence in such way that resulting value is divisible by K. In the above example, the sequence is divisible by 7 (17+5+-21-15=-14) but is not divisible
by 5.
You are to write a program that will determine divisibility of sequence of integers.
Input
The first line of the input contains two integers, N and K (1 <= N <= 10000, 2 <= K <= 100) separated by a space.
The second line contains a sequence of N integers separated by spaces. Each integer is not greater than 10000 by it's absolute value.
Output
Write to the output file the word "Divisible" if given sequence of integers is divisible by K or "Not divisible" if it's not.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Sample Input
2
4 7
17 5 -21 15
4 5
17 5 -21 15
Sample Output
Divisible
Not divisible
【问题分析】http://blog.csdn.net/tsaid/article/details/7840487(可怜原作者不晓得输出的恶心换行套路,找错绝对很头疼)
看到题目第一个反映就是枚举中间添的运算符,算出值在MOD K如果有一个值MOD K=0则输出“Divisible”。
时间复杂度是O(2N-1)。
但是题目给出的数据量很大,这样做效率太低了。
因为题目涉及MOD运算,要想简化问题就需要知道一些基本的MOD运算性质:
A*B mod C=(A mod C*B mod C) mod C
(A+B) mod C=(A mod C+B mod C) mod C
有了这个性质,我们就可以把累加后求余转化成求余后累加(我们把减法看作加负数以后分析只说加法)再求余。这样我们的读入数据就控制在了1-K到K-1的范围内了。
我们要判断的就是
所有结果的累加和 MOD K 是否为0。简记为:
(A+B)mod K=0 or (A+B) mod K<>0
如果我们按数的个数划分阶段,前N-1个数的运算结果 MOD K看做A,第N个数看作B就OK了。
于是我们想到了这样的状态:opt[i,j]表示前i个数是否可以得到余数为J的结果。
那么状态转移方程就是
opt[i,(j-a[i] mod k )modk]=opt[i-1,j] (opt[i-1,j]=true);
opt[i,(j+a[i] mod k) modk]=opt[i-1,j] (opt[i-1,j]=true);
如果opt[n,0]=true就输出‘Divisible’
我一开始想用滚动数组来解决(尽管没有这个必要)。
a[1][(x%k+k)%k]=true;
for(int i=2;i<=n;i++)
{
cin>>x;//=_S();
for(int j=0;j<k;j++)
{
if(a[(i-1)%2][j])
{
a[i%2][((j+x)%k+k)%k]=true;
a[i%2][((j-x)%k+k)%k]=true;
}
}
}
if(a[n%2][0]==true) printf("Divisible\n");
else printf("Not divisible\n");
if(T) printf("\n");
然后一直wa,后来发现滚动数组必须每次刷新,很尴尬,反而使得效率低下。如下:
memset(a[1],false,sizeof(a[1]));
x=_S();
a[1][(x%k+k)%k]=true;
for(int i=2;i<=n;i++)
{
memset(a[i%2],false,sizeof(a[i%2]));
x=_S();
for(int j=0;j<k;j++)
{
if(a[(i-1)%2][j])
{
a[i%2][((j+x)%k+k)%k]=true;
a[i%2][((j-x)%k+k)%k]=true;
}
}
}
if(a[n%2][0]) printf("Divisible\n");
else printf("Not divisible\n");
if(T) printf("\n");
就是memset这个可恶的东西,然后改了一下:
a[1][(x%k+k)%k]=1;
for(int i=2;i<=n;i++)
{
x=_S();
for(int j=0;j<k;j++)
{
if(a[(i-1)%2][j]==i-1)//用唯一的数字标记,不需要更新
{
a[i%2][((j+x)%k+k)%k]=i;
a[i%2][((j-x)%k+k)%k]=i;
}
}
}
if(a[n%2][0]==n) printf("Divisible\n");
else printf("Not divisible\n");
if(T) printf("\n");
但是搞来搞去,好像效率还是不怎么样,不过数字代替memset的思路是挺好的。
建议赛场上还是开a[10001][101]的数组,免得乱搞麻烦。
完整代码:100ms,还算可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<memory.h>
#include<cmath>
using namespace std;
int a[2][101];
int _S()
{
char c=getchar();
while(c<'0'||c>'9')
c=getchar();
int s=0;
while(c>='0'&&c<='9'){
s=s*10+c-'0';
c=getchar();
}
return s;
}
int main()
{
int T,k,x,n;
T=_S();
while(T--)
{ n=_S();
k=_S();
memset(a,0,sizeof(a));
x=_S();
a[1][x%k]=1;
for(int i=2;i<=n;i++)
{
x=_S();
for(int j=0;j<k;j++)
{
if(a[(i-1)%2][j]==i-1)
{
a[i%2][(j+x)%k]=i;
a[i%2][((j-x)%k+k)%k]=i;
}
}
}
if(a[n%2][0]==n) printf("Divisible\n");
else printf("Not divisible\n");
if(T) printf("\n");
}
return 0;
}
ZOJ 2042 Divisibility (DP)的更多相关文章
- ZOJ - 2042 模运算DP
解法见网上参考 这种只判断可达性的DP一般用bool 除非int能得到更多的信息 #include<iostream> #include<algorithm> #include ...
- ZOJ 3626(树形DP+背包+边cost)
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3626 题目大意:树中取点.每过一条边有一定cost,且最后要回 ...
- zoj 3822 Domination(dp)
题目链接:zoj 3822 Domination 题目大意:给定一个N∗M的棋盘,每次任选一个位置放置一枚棋子,直到每行每列上都至少有一枚棋子,问放置棋子个数的期望. 解题思路:大白书上概率那一张有一 ...
- ZOJ 3201 树形dp+背包(简单题)
#include<cstdio> #include<vector> #include<cstring> #include<iostream> using ...
- ZOJ 3805 (树形DP)
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5337 题目大意:方块连接,呈树形.每个方块有两种接法,一种接在父块 ...
- ZOJ 3822 可能性DP
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3822 本场比赛之前,我记得.见WALK概率路DP称号.那么它应该是可以考虑 ...
- zoj 3640 概率dp
题意:一只吸血鬼,有n条路给他走,每次他随机走一条路,每条路有个限制,如果当时这个吸血鬼的攻击力大于等于某个值,那么就会花费t天逃出去,否则,花费1天的时间,并且攻击力增加,问他逃出去的期望 用记忆化 ...
- ZOJ 3211dream city dp(效率优化)
Dream City Time Limit: 1 Second Memory Limit:32768 KB JAVAMAN is visiting Dream City and he see ...
- zoj 3537 区间dp+计算几何
题意:给定n个点的坐标,先问这些点是否能组成一个凸包,如果是凸包,问用不相交的线来切这个凸包使得凸包只由三角形组成,根据costi, j = |xi + xj| * |yi + yj| % p算切线的 ...
随机推荐
- Day-9: 面对对象高级编程
数据封装.继承和多态只是面向对象编程中最基础的3个概念. 下面整理面向对象高级编程的更为强大的技巧. 使用__slots__:Python属于动态语言,可以允许已创建好的类动态地绑定任何属性和方法.但 ...
- cocos2dx lua中异步加载网络图片,可用于显示微信头像
最近在做一个棋牌项目,脚本语言用的lua,登录需要使用微信登录,用户头像用微信账户的头像,微信接口返回的头像是一个url,那么遇到的一个问题就是如何在lua中异步加载这个头像,先在引擎源码里找了下可能 ...
- PHP中如何调试?
比如有个数组: $arr = array('A' => 'bobi','B' => 'hehe'); echo $arr; //Array 只打印出了变量 ...
- JS学习四(BOM DOM)
BOM Screen对象 console.log(window.width);//屏幕宽度 console.log(window.height);//屏幕高度 conso ...
- 英语学习案例分析APP 201421123108 王坤彬
第一部分.调研,测评 1.第一次使用经验. 我使用的时候苹果手机下载的必应软件.第一次使用感觉还好,但是知名度比较低,比不上喜马拉雅听书软件,这里我就做两者的对比.首先界面以及种类明显逼格更差点.必应 ...
- 201521123107 《Java程序设计》第9周学习总结
第9周作业-异常 1.本周学习总结 2.书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什 ...
- 201521123051 《Java程序设计》 第二周学习总结
1. 本周学习总结 1.学会使用码云:学会如何将项目同步到码云中以及从码云上的项目保存到本地. 2.各数据类型的使用. 3.运算符和表达式的使用. 4.string创建之后不可在修改. 5.Java程 ...
- 201521123108《Java程序设计》第1周学习总结
本周学习总结 刚加入java的学习,我感觉很困难.但我觉得学习并不是一蹴而就.只要我多读,多看,多练,一定会取得进步.有空的时候把书本上的代码敲一敲.相信会有回报. 2.书面作业 1.为什么java程 ...
- 201521123105 第9周Java学习总结
1. 本周学习总结 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避 ...
- Thrift教程初级篇——thrift安装环境变量配置第一个实例
前言: 因为项目需要跨语言,c++客户端,web服务端,远程调用等需求,所以用到了RPC框架Thrift,刚开始有点虚,第一次接触RPC框架,后来没想到Thrift开发方便上手快,而且性能和稳定性也不 ...