Luogu P1356 【数列的整数性】题解

对于什么模什么整除之类的DP题我总是很慌张

但是像我这种蒟蒻都过了这道题是不是?

对于这种能否整除的DP题目,我们只需要考虑前i个数通过一定的组合,mod k 能否 == j,
这就是我们要写的`状态`

bool f[i][j]表示能否通过一定的组合将前i个数 mod k = j;

显而易见,最后的答案是能否通过一定的组合将前n个数 mod k = 0
也就是f[n][0]是否为true;

当状态为f[i][j]时,若状态f[i][(j +- a[i] % k + k) % k] 为true,则f[i][j]也一定为true;+-里只要满足一个就可以了,所以要用||符号

最后头疼的是边界条件,卡了我很久

f[1][(a[1] % k + k) % k] = f[1][(-a[1] % k + k) % k] = true;

#include <bits/stdc++.h>
using namespace std;

int t,n,k;
bool f[10000 + 10][100 + 10];
int a[10000 + 10];

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        memset(f,0,sizeof(f));
        for(int i = 1;i <= n; i++) scanf("%d",&a[i]);
        f[0][0] = 1;
        f[1][(a[1] % k + k) % k] = f[1][(-a[1] % k + k) % k] = true;
        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 + k) % k]);
            }
        }
        printf("%s\n",f[n][0] == 1 ? "Divisible" : "Not divisible");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/chloristendika/p/9240924.html

时间: 2024-08-08 00:49:02

Luogu P1356 【数列的整数性】题解的相关文章

【luogu P3901 数列找不同】 题解

对于区间查询的问题,提供一种思路: 莫队. 莫队是处理区间问题的乱搞神器,尤其是对于离线查询问题,当然也可以做在线查询,比如带修莫队. 对于有的题,莫队是乱搞骗分,而在某些地方,莫队是正解. 这道题来说,可以当做是萌新初学莫队的一个板子,而且莫队也好理 解.线段树树状数组这类也可以做,但是相比莫队而言麻烦些.(个 人见解,不喜勿喷.谢谢) 1st.关于莫队的思想: 先明白一点,莫队可以理解成: 优雅的暴力. 暴力算法几乎人人都会,所以莫队理解起来好理解. 如果让你暴力的话呢? 我们用一个cnt[

Luogu P1062 数列

Luogu P1062 数列 题目说: 把所有\(k\)的方幂及所有有限个互不相等的\(k\)的方幂之和构成一个递增的序列. 这就是说,每一个\(k\)的方幂只能有或没有. 有为\(0\),没有为\(1\). 所以这些数在二进制下是这样的: \(1,10,11,100,101,110,111,1000\cdots\) 所以,第\(n\)项在十进制里就是\(n\). #include<bits/stdc++.h> using namespace std; int k,n,len; int num

Luogu P1352 没有上司的舞会 题解

Luogu P1352 没有上司的舞会   [传送门] 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会, 宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了. 所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数. 输入输出格式 输入格式: 第一行一个整数N.(1<=N<=6000) 接下来N行,第

luogu P1182 数列分段Section II

题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 2][4 5][1] 第一段和为6,第2段和为9,第3段和为1,和最大值为9. 将其如下分段: [4][2 4][5 1] 第一段和为4,第2段和为6,第3段和为6,和最大值为6. 并且无论如何分段,最大值不会小于6. 所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6. 输

luogu p1799 数列_NOI导刊2010提高(06)

原题链接 https://www.luogu.org/problem/show?pid=1799 我一开始觉得这个题真是玄学,直到我发现自己没有写max之后...(逃) f[i][j]表示前i个删了j个时的最优解,对于第i个数,如果前面删去j个数时,能使a[i]==i,f[i][j]的值就会增加1; 但这样是不是就是最大了呢,不一定.如果此时f[i-1][j-1]很大的话,f[i-1][j]+1仍然较小,此时就不如不删除. 不管删去j的数后能否使a[i]==i,f[i][j]都等于f[i-1][

luogu P1181 数列分段Section I x

P1181 数列分段Section I 题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成连续的若干段,并且每段和不超过M(可以等于M),问最少能将其分成多少段使得满足要求. 输入输出格式 输入格式: 输入文件divide_a.in的第1行包含两个正整数N,M,表示了数列A[i]的长度与每段和的最大值,第2行包含N个空格隔开的非负整数A[i],如题目所述. 输出格式: 输出文件divide_a.out仅包含一个正整数,输出最少划分的段数. 输入输出样例 输入样例#1: 5 6 4

【luogu P1865 A % B Problem】题解

题目链接:https://www.luogu.org/problemnew/show/P1865 其实就是埃拉托色尼筛素数模板... 好像每个数暴力枚举到sqrt()也可以...就算当我无聊练手罢 1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const int maxn = 1000000

【luogu P2023 [AHOI2009]维护序列】 题解

题目链接:https://www.luogu.org/problemnew/show/P2023 把P3373改一改直接粘过来就A 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define lson left, mid, rt<<1 6 #define rson mid+1, right, rt<<1|

【luogu P1144 最短路计数】 题解

题目链接:https://www.luogu.org/problemnew/show/P1144 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <queue> 5 #include <vector> 6 using namespace std; 7 const int mod = 100003; 8 const int maxn = 2000