UVA - 12063(关于倍数的dp转化成模运算)

本文介绍了一种使用动态规划解决特定数值组合问题的方法。针对给定长度n和模数K的情况下,如何计算所有可能的二进制序列中,包含恰好n/2个1且整个序列对K取模等于特定值的数目。通过递归状态转移方程实现,并考虑边界条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

</pre>以状态d(i,j,k)代表第前i位用j个一能组成所有对K取模余数为k的数状态转移即该位置为1还是0<p>还有一点要说明 最后结果不是d(n-1,n/2-1,K-yu[n] (yu[n]为2^(n-1)对K取模后的值)  ) 而是d(n-1,n/2-1,(K-yu[n])%K);</p><p><pre name="code" class="html">#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 66;
const int maxk = 105;
long long d[maxn][maxn][maxk];
bool vis[maxn][maxn][maxk];
int yu[maxn],n,K;
long long dp(int i,int j,int k){
    if(vis[i][j][k]) return d[i][j][k];
    vis[i][j][k]=true;
    if(i==0){
        if(j!=0) return d[i][j][k]=0;
        return d[i][j][k] = (k%K==0 ? 1 : 0);
    }
    d[i][j][k]=dp(i-1,j,k);
    if(j>0) d[i][j][k]=d[i][j][k]+dp(i-1,j-1,(K+k-yu[i])%K);
    return d[i][j][k];
}
int main()
{
   int T;
   scanf("%d",&T);
   int kase=1;
   while(T--){
       scanf("%d %d",&n,&K);
       printf("Case %d: ",kase++);
       if(n&1||K==0) printf("0\n");
       else{
           yu[1]=1;
           for(int i=2;i<=n;i++){
                yu[i]=(yu[i-1]*2)%K;
           }
           memset(vis,false,sizeof(vis));
           long long temp = dp(n-1,n/2-1,(K-yu[n])%K );
           printf("%lld\n",temp);
       }
   }
}





                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值