1 条题解
-
0
自动搬运
来自洛谷,原作者为

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
- 上传者