判断整除

【题目】

    一个给定的正整数序列,在每个数之前都插入+号或-号后计算它们的和。所有结果中至少有一个可被整数k整除,我们则称此正整数序列可被k整除。

    现判断一个正整数序列是否能被k整除。输入的第一行包含两个数:N(2 < N < 10000)和k(2 < k< 100),其中N代表一共有N个数,k代表被除数。

    第二行给出序列中的N个整数,这些整数的取值范围都0到10000之间(可能重复)。

【题目链接】

    http://noi.openjudge.cn/ch0206/3531/

【分析】

    1.  所谓递推就是一个问题与其子问题有一定的关系,为求解问题,应从子问题入手并记录子问题能提供的数据(及其状态),通过子问题的数据/状态逐步将子问题扩展为原问题。

    2.  该题的子问题就是该序列前i个数能否被k整除

    3.  再来看子问题状态,若仅仅提供该问题能否被k整除无法确定状态,根据mod运算的性质【(a+b)%k = (a%k+b%k)%k】不难想到,任意状态的值并不需要均求出来,而且任意两个状态如果相差k的整数倍则可将这两个状态视为等价,所以任意状态可映射到其对k取模之后的余数上去,当且仅当两个状态对k取模后余数相等可将这两个状态视为等价。由于一个子问题可能映射到多个余数,而k为2~100,所以定义子问题状态【bool 数组 b[i][j]的值表示序列前i个数所包含的状态除k余数是否可能为j】

    4.  再来看状态转移,若b[i-1][j]=1则b[i][(j+a[i]) % k] = 1, b[i][(j-a[i]+k) % k] = 1;初始情况则是b[1][a[1]] = 1;

【代码】

 1 #include <iostream>
 2 using namespace std;
 3 int n,i,j,k;
 4 int a[10010];
 5 bool b[10010][110];
 6 int main()
 7 {
 8     cin>>n>>k;
 9     for(i = 1; i <= n; i++) cin>>a[i],a[i]%=k;
10     b[1][a[1]] = 1;
11     for(i = 2; i <= n; i++)
12         for(j = 0; j < k; j++)
13             if(b[i-1][j])
14                 b[i][(a[i]+j)%k] = 1,
15                 b[i][(j-a[i]+k)%k] = 1;
16     if(b[n][0]) cout<<"YES";
17     else cout<<"NO";
18 }

 

转载于:https://www.cnblogs.com/Willendless/p/9322414.html

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值