• 判断整除


    判断整除

    链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1195


    时间限制: 1000 ms         内存限制: 65536 KB

    【题目描述】

    一个给定的正整数序列,在每个数之前都插入+号或-号后计算它们的和。比如序列:1、2、4共有8种可能的序列:

    (+1) + (+2) + (+4) = 7

    (+1) + (+2) + (-4) = -1

    (+1) + (-2) + (+4) = 3

    (+1) + (-2) + (-4) = -5

    (-1) + (+2) + (+4) = 5

    (-1) + (+2) + (-4) = -3

    (-1) + (-2) + (+4) = 1

    (-1) + (-2) + (-4) = -7

    所有结果中至少有一个可被整数k整除,我们则称此正整数序列可被k整除。例如上述序列可以被3、5、7整除,而不能被2、4、6、8……整除。注意:0、-3、-6、-9……都可以认为是3的倍数。

    【输入】

    输入的第一行包含两个数:N(2<N<10000)和k(2<k<100),其中N代表一共有N个数,k代表被除数。第二行给出序列中的N个整数,这些整数的取值范围都0到10000之间(可能重复)。

    【输出】

    如果此正整数序列可被k整除,则输出YES,否则输出NO。(注意:都是大写字母)

    【输入样例】

    3 2
    1 2 4
    法一:搜索,对于每个数非正即负,用X代表抉择,F[i]表示选到第i个数得到答案
    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cmath>
    using namespace std;
    int f[10005],a[10005];
    int n,k,cnt;
    void dfs(int i,int x){
        
        if(i==n+1)
        {
            if(cnt){
                return ;
            }
            f[i-1]=abs(f[i-1]);
            if(f[i-1]%k==0)
                cnt=1;
            return ;                
        }
        if(cnt){
            return ;
        }
        if(x)f[i]=f[i-1]+a[i];
        else f[i]=f[i-1]-a[i];
        dfs(i+1,0);    
        dfs(i+1,1);
    
    }
    int main()
    {
        int ans=0;
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            ans+=a[i];
        }
        f[0]=0;
        if(ans%2&&k%2==0);    
        else {
            dfs(1,0);
            if(cnt){
                cout<<"YES"<<endl;
                return 0;
            }
            else {
                dfs(1,1);
                if(cnt){
                    cout<<"YES"<<endl;
                    return 0;
                }
            }
        }
        
        if(!cnt)cout<<"NO"<<endl;
        return 0;
    }
    
    

    法二:递推,f[i][j]表示用了第i个数能否使余数为j,若f[n][0]为真则成立,得到转移方程:

     f[i][j]=(f[i-1][((j-a[i])%k+k)%k]||f[i-1][(j+a[i])%k]);//加上k是为了使下标大于1   →(a*b)%c=(a%c+b%c)%c;

    对于边界1可只考虑+或-,因为一种情况整体乘-1就得到另一种情况,见样例

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    bool f[10005][205];
    int a[10005];
    int main()
    {
        int n,k;
        cin>>n>>k;
        for(int i=1;i<=n;i++)cin>>a[i];
        f[1][(a[1]%k+k)%k]=1;
        for(int i=2;i<=n;i++)
            for(int j=0;j<k;j++){
                f[i][j]=(f[i-1][((j-a[i])%k+k)%k]||f[i-1][(j+a[i])%k]);
        }
        if(f[n][0])cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }


  • 相关阅读:
    【java】报错could not find the main class,program will
    CSS3——阴影
    SSO单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析
    SSO单点登录系列3:casserver端配置认证方式实践
    [转载] jQuery Mobile 开发 Web App 系列文章目录
    SHELL基本语法2
    SHELL编程基本语法
    如何写批处理文件
    LINUX shell-快速参考[一]
    Shell中的引号,反引号,双引号,反斜杠
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/7530590.html
Copyright © 2020-2023  润新知