UVA 12063 Zeros and Ones(三维dp)
题意:给你n、k,问你有多少个n为二进制的数(无前导零)的0与1一样多,且是k的倍数
题解:对于每个k都计算一次dp,dp[i][j][kk][l]表示i位有j个1模k等于kk且第一位为l(0/1)
再次预处理mod[i][j]表示1的i次方模j等于几,具体看代码注释
import java.util.Scanner; public class Main{ static int Maxn=65; static int Maxk=101; //前i个数有j个1模给定的值余k且第一位为1或者0的总个数 static long[][][][] dp = new long[Maxn][Maxn][Maxk][2]; //初始化1的i次方模j等于几 static int[][] Mod=new int[Maxn][Maxk]; //初始化 static void Init(){ for(int i=0;i<Maxn;++i){ for(int j=1;j<Maxk;++j){ Mod[i][j]=(int) ((1L << i)%j); } } } //按位dp求出当有n位是模kk等于0的总个数 static long Solve(int n,int kk){ if(kk==0||(n&1)==1)//特判 return 0L;for(int i=0;i<=n;++i)//初始化 for(int j=0;j<=i;++j) for(int k=0;k<=kk;++k){ dp[i][j][k][0]=dp[i][j][k][1]=0L; } dp[0][0][0][0]=1L; //每种dp的i位只与i-1位相关 for(int i=1;i<=n;++i){ //求i位有i/2个1时需要i-1位有i/2与i/2-1个1,但是再向前推就需要更多所以将出现所有可能个1的情况求出 for(int j=0;j<=i&&j<=n/2;++j){ //模kk等于所有k的情况都需要求出,用于下一次使用 for(int k=0;k<kk;++k){ //此位置放0 dp[i][j][k][0]+=dp[i-1][j][k][0]+dp[i-1][j][k][1]; //此位置放1,k就等于前一个是当前位置减去(1<<i-1)后再模kk的值 if(j>0){ dp[i][j][k][1]+=dp[i-1][j-1][(k+kk-Mod[i-1][kk])%kk][0]+dp[i-1][j-1][(k+kk-Mod[i-1][kk])%kk][1];//计算余数 } } } } return dp[n][n/2][0][1]; } public static void main(String[] args) { int t,coun=0; int n,k; Init(); Scanner sc =new Scanner(System.in); t=sc.nextInt(); while(t!=0){ n=sc.nextInt(); k=sc.nextInt(); System.out.println("Case "+(++coun)+": "+Solve(n,k)); t--; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决