1 条题解

  • 0
    @ 2025-8-24 21:24:09

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar LJC00118
    Alice foo foo!

    搬运于2025-08-24 21:24:08,当前版本为作者最后更新于2017-11-13 14:05:45,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这道题一看就是标准的DP

    我们可以用背包问题的思路去做

    这个程序的优点是运行速度快,内存小

    为什么会快而且内存小呢

    * 我们边加边模k,结果不变

    * 在读入时没有将其储存,直接DP

    证明思路正确如下:

    设有n个数为a1,a2,a3……,an

    先将其全模k得到余数

    余数相加再模k

    若(a1+a2-a3-a4+a5+......-an)%k==0则它们的余数(b1+b2-b3-b4+b5+......-bn)%k也为0

    因为他们都是可爱的余数......

    这样我们只要开101的空间就够用了(k<=100)

    以下是代码(自带注释)

    #include<bits/stdc++.h>//万能的头文件
    using namespace std;
    int n,k,e=0,nn;
    int f[101],opt[101][2];
    int main()
    {
        scanf("%d",&nn);                                                                                                                                                                                    防抄袭
        for(int i=1;i<=nn;i++)//循环n次
        {
            memset(f,-1,sizeof(f));//数组清负1
            cin>>n>>k;//读入n和k
            f[0]=0;//f[0]可以做到
            for(int i=1;i<=n;i++)
            {
                int tmp;//读入n个数,基本不用内存
                scanf("%d",&tmp);
                tmp=(tmp%k+k)%k;//因为有负数,所以不能写tmp=tmp%k,-21%5=-1
                e=0;//第e个数
                for(int j=k-1;j>=0;j--)
                {
                    if(f[j]==i-1)//因为我们要用上所有的数,所以在i-1个数都用上的时候才能进行下一次DP
                    {                                                                                                                                                                                      防抄袭
                        opt[++e][0]=f[j];//精髓部分,用链表的思想储存
                        opt[e][1]=j;//同上
                        /*int tmp_fj=f[j];
                        f[(j+tmp)%k]=tmp_fj+1;
                        f[(j-tmp+k)%k]=tmp_fj+1;*/ 
                    }
                }
                for(int j=e;j>=1;j--)
                {
                    f[(opt[j][1]+tmp)%k]=opt[j][0]+1;//选择加这个数,边加边模k
                    f[(opt[j][1]-tmp+k)%k]=opt[j][0]+1;//选择减这个数,边减边模k
                }
            }
            if(f[0]==n) puts("Divisible");//如果模0可以用n个数做到,输出Divisible
            else puts("Not divisible");//不说了
        }                                                                                           防抄袭
        return 0;
    }
    
    • 1

    信息

    ID
    354
    时间
    1000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者