题目解析
33.卡牌翻面求和问题
题意:
我们需要找到一种方法,使得从n张卡牌中选择每张卡牌的一面(正面或背面),使得所有选择的数字之和可以被3整除。由于可能的方案数量很大,结果需要对1e9+7取模。
虽然是一道困难题,但实际上只要掌握了动态规划的思维,这道题还是很套路的。
动态规划的一般步骤如下:
-
状态表示: 设
f[i][j]
表示前i
张卡牌中,选择某些面使得数字之和模3余j
的方案数。 -
初始化:
f[0][0] = 1
,表示前0张卡牌中,数字之和取模为0的方案数为,因为没有选数字,只有一种可能。 -
状态转移: 对于每一张卡牌
i
,我们可以选择它的正面a[i]
或背面b[i]
。选择正面,那么余数就变成了(j+a[i])%3
f[i+1][(j+a[i])%3] = (f[i+1][(j+a[i])%3] + f[i][j]) % mod
选择反面,那么余数就变成了(j+b[i])%3
f[i+1][(j+b[i])%3] = (f[i+1][(j+b[i])%3] + f[i][j]) % mod
核心代码如下:
public class Main {
public static int solution(int n, int[] a, int[] b) {
// write code here
int mod=(int)1e9+7;
int[][] f =new int[n+2][3];
f[0][0]=1;
for(int i=0;i<n;i++){
for(int j=0;j<3;j++){
f[i+1][(j+a[i])%3]=(f[i+1][(j+a[i])%3]+f[i][j])%mod;
f[i+1][(j+b[i])%3]=(f[i+1][(j+b[i])%3]+f[i][j])%mod;
}
}
return f[n][0];
}
}
工具运用与心得
使用豆包AI刷题对于算法小白来说还是很不错的,即使是像我这样有一定算法基础的人有时候也要AI的帮助才能顺利AC一道题目。
在面对一些比较复杂的题目时,我们可能会在某些点上卡住导致无从下手。但有了AI的帮助,我们可以选择“需要一点思路提示”,这样可以帮我们快速地打开思路,并确定算法的设计和代码的框架,之后我们就可以在AI给我们的代码基础上进行补充、完善具体细节。不过有时候AI给的思路不一定是对的,需要有自己的思考和判断。当然,在写完一道题的代码之后,如果提交显示没有通过,我们也可以点击“帮我检查一下编辑区的代码”让AI帮我们debug。
学习方法
对于想要快速入门算法的同学,我有一些建议。新手切忌胡乱刷题,只关注刷题量不关注自己掌握哪些类型是不行的。在AI刷题主界面我们可以看到上方有分类,可以先去学习对应的知识点和代码模板在去系统性的刷这部分题。如果一道题卡了20分钟也没有做出来,就不要再死磕了,可以找AI帮忙,也可以在自己实力强了之后在回过头来看。比如图论这部分像最短路、最小生成树需要掌握对应的算法模板,否则想破脑袋也想不出来的。