题解:UVA10036 Divisibility

水,不知道怎么评的绿。

Solution UVA10036

Idea

dpi,jdp_{i,j} 表示前 ii 个数,和对 kk 取模的值为 jj 的状态是否可行。

则显然有:dpi,j=max(dpi1,(jai) modk,dpi1,(j+ai) modk)dp_{i,j}=\max(dp_{i-1,(j-a_i)\bmod k},dp_{i-1,(j+a_i)\bmod k})

初始值显然是 dp1,a1 modk=1dp_{1,a_1\bmod k}=1

然后判断 dpn,0dp_{n,0} 是否为 11 即可。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=10005,M=105;
int dp[N][M],n,a[N],mod;
void solve(){
	memset(dp,0,sizeof(dp));
	scanf("%d%d",&n,&mod);//mod 为原题中的 k
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		a[i]%=mod;//先对 mod 取模,减少后面码量
	}
	dp[1][(a[1]+mod)%mod]=1;
	for(int i=2;i<=n;i++){
		for(int j=0;j<mod;j++){
			dp[i][j]=max(dp[i-1][(j-a[i]+mod)%mod],dp[i-1][(j+a[i]+mod)%mod]);
            //注意到 a[i] 可以小于 0,所以要先加 mod。
		}
	}
	if(dp[n][0])printf("Divisible\n");
	else printf("Not divisible\n");
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--)solve();
	return 0;
}

提供另外一种代码思路,使用刷表,更好理解。

dp[1][(a[1]+mod)%mod]=1;
for(int i=2;i<=n;i++){
	for(int j=0;j<mod;j++){
		if(dp[i-1][j])dp[i][(j-a[i]+mod)%mod]=1;
		if(dp[i-1][j])dp[i][(j+a[i]+mod)%mod]=1;
	}
}
if(dp[n][0])printf("Divisible\n");
else printf("Not divisible\n");

如果你想压行,也可以在转移里这么写:

dp[i][(j-a[i]+mod)%mod]|=dp[i-1][j];
dp[i][(j+a[i]+mod)%mod]|=dp[i-1][j];
posted @   Weslie_qwq  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示