zoukankan      html  css  js  c++  java
  • 百练1745:Divisibility

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述
    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. 
    输入
    The first line of the input file 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. 
    输出
    Write to the output file the word "Divisible" if given sequence of integers is divisible by K or "Not divisible" if it's not.
    样例输入
    4 7
    17 5 -21 15

    样例输出

    Divisible

    题目分析:

      题目大意是给你一串数字,第一个数字不能改变,第2~n个数字可以变为相反数。判断这些数字的和是否能被k整除。

      因为1 <= N <= 10000, 2 <= K <= 100,因此普通的DFS必定会超时。

    解决方案一:DFS 加上一定的剪枝处理

    #include <cstdio>
    #include <cstring>
    int n,m;
    bool jud = false;
    int a[10001];
    int v[10001][101];
    void dfs(int cur, int x)
    {
         if (jud)
             return;
         if (x==n-1&&cur%m==0)
         {
             jud=1;
             return;
         }
         else if (x==n-1)
             return;
         v[x][cur]=1;
         int plus=(cur+a[x+1])%m;
         if (x==n-2&&!plus)
         {
             jud=1;
             return;
         }
         else if (!v[x+1][plus])
             dfs(plus, x+1);
         int minus=(cur-a[x+1])%m;
         if (x==n-2&&!minus)
         {
             jud=1;
             return;
         }
         else if (!v[x+1][minus])
             dfs(minus, x+1);
     }
    int main()
    {
         scanf("%d %d", &n, &m);
         for (int i=0; i<n; i++)
             scanf("%d", &a[i]), a[i]=a[i]%m;
         dfs(a[0], 0);
         printf("%s
    ", jud?"Divisible":"Not divisible");
         return 0;
    }

    解决方案二:dp,参照的poj Discuss区的代码

    用dp[i-1][j] 表示前i-1行 出现过j 这个数;

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    bool dp[10001][101];
    long num[10001];
    int main()
    {
        int n,k;
        cin>>n>>k;
        for(int i=1;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            num[i]=a%k;
        }
        dp[0][0]=true;
     for(int i=1;i<=n;i++)
     {
         for(int j=k-1;j>=0;j--)
             if(dp[i-1][j])
             {
                 dp[i][(j+num[i])%k]=1;
                 dp[i][(k+j-num[i])%k]=1;
             }
     }
     if(dp[n][0])
         printf("Divisible
    ");
     else
         printf("Not divisible
    ");
    return 0;
    }

     方案三:Discuss中的,算是hash吧,代码比较简洁易懂,并且省空间!!!

    #include <iostream>
    using namespace std;
    int main()
    {
        int a[100],n,k,i;
           for(i=0;i<100;i++)
            a[i]=0;
           cin >> n >> k;
            int temp;
            cin >> temp;
            a[(temp%k + k)%k]=1;
           for(int i=2;i<=n;i++)
            {
                int b[100];
                for(int j=0;j<100;j++)
                    b[j]=0;
                cin >> temp;
                for(int l=0;l<k;l++)//新输入的数与上轮存在的余数进行加和减运算
                {
                    if(a[l])      //就是此处的l被我写成了i,最开始
                    {
                        b[((l+temp)%k+ k)%k]=1;
                        b[((l-temp)%k+ k)%k]=1;
                    }
                }
                for(int j=0;j<k;j++)
                    a[j]=b[j];//某一轮输入结束后,所有存在的余数对应的a数组值取1,别的置0
            }
            if(a[0])cout << "Divisible" << endl;//最后一轮输入结束后,看是否有余数为0,即能整除的结果
            else cout << "Not divisible" << endl;
    
        return 0;
    }
  • 相关阅读:
    [转]Amazon DynamoDB – a Fast and Scalable NoSQL Database Service Designed for Internet Scale Applications
    [转]CIDR简介
    [转]Amazon AWS亚马逊云服务免费一年VPS主机成功申请和使用方法
    [转]SQL Server 连接串关键字别名
    [转]各种符号的英文单词
    【解决】SharePoint 2013 当鼠标悬停在用户名称上时页面会崩溃
    【HOW】如何限制Reporting Services报表导出功能中格式选项
    【解决】“不能手工移动或复制项到放置库”
    【解决】SharePoint 2013 with SP1安装问题及解决
    [转]安装SharePoint 2013时安装AppFabric失败(错误码:1603)
  • 原文地址:https://www.cnblogs.com/starryxsky/p/7117323.html
Copyright © 2011-2022 走看看