【DP】:CF #319 (Div. 2) B. Modulo Sum
【题目链接】:http://codeforces.com/contest/577/problem/B
【相似题目】:http://swjtuoj.cn/problem/2383/
【题意】:给出n个数,问是否能从中选出一些数,使得这些数的和是m的倍数。
【题解】:
首先,先明白这样一个事实:
设:sum%dend=rem;
(sum:一些数的和,dend:被除数,rem:余数)
则有:(rem+n)%dend=(sum+n)%dend;
(n为一个新的数)
知道了上面的等式之后,题目就好做了:
设:est[rem]=1 表示存在余数rem,它是通过一些数的和sum%dend得到的。
对于每一个给定的n,
考察 1<=rem<=dend-1 范围内的est[rem],即考察是否存在之前一些数的和sum%dend=rem(不管sum是之前的数是怎么相加得来的)
若存在,即est[rem]=1,则可以通过(rem+n)%dend来求出新的余数,即令est[(rem+n)%dend]=1;
此外,n%dend也是新的余数,即est[n%dend]=1;
若在上面的余数中有一个等于0,即est[0]=1,则说明存在dend的倍数,直接中断循环。
【注意】
在对每一个n的循环中,不能立刻更新est数组,原因是某些情况会导致出错。
出错例子:
设:已有est[1]=1,此时n=1,dend=100;
若令est[(1+n)%dend]=1,即est[2]=1,
则又有est[(2+n)%dend]=1,即est[3]=1,
又有est[(3+n)%dend]=1,即est[4]=1......
最后整个est数组都为1,显然这是错误的。
所以,要一个 i_est 数组来临时更新est数组,最后再更新est数组(详见代码)。
#include<stdio.h>
int num,dend,t,i,n[];
char est[],i_est[];
int main(){
scanf("%d%d",&num,&dend);
for(t=;t<num;t++){
scanf("%d",&n[t]);
}
for(t=;t<num;t++){
for(i=;i<dend;i++){
if(!est[i]) continue;
i_est[(i+n[t])%dend]=;
}
i_est[n[t]%dend]=;
for(i=;i<dend;i++){
est[i]=i_est[i];
}
if(est[]) break;
}
if(est[]){
printf("YES\n");
}
else{
printf("NO\n");
}
return ;
}
最新文章
- [word]用Word2007查找和替换功能批量设置图片位置
- 时间控件之赋值问题:datetimebox
- 简单的跨平台c/c++日志记录
- iOS自定义字体
- 源码编译安装screen
- jquery中使用event.target的几点
- unity, 顶点对齐
- jquery上传图片插件plupload
- 多线程中lock用法的经典实例
- js实现Mac触摸板双指事件(上、下、左、右、放大、缩小)
- DirectX 11---从空间变换来看3D场景如何转化到2D屏幕
- 支付宝使用流程和踩坑小记(附Demo)
- java程序高CPU,如何直接定位(linux系统下命令行操作)
- Spring MVC参数封装传递
- python --github 刷题
- RHEL/CentOS/Fedora各种源
- DB2 SQL1477N问题
- java web 项目启动的根目录,以及项目启动后使用的端口具体是哪一个
- beat冲刺(6/7)
- Linux内核设计与实现第八周读书笔记