HDU 1438 钥匙计数之一 递推+组合 简洁的做法

本文探讨了一把具有特定槽深规则的锁匙计数问题,通过编程算法解决了当锁匙长度从2到31时,符合特定条件的锁匙数量。文章提供了完整的AC代码及打表代码。

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



钥匙计数之一

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1662    Accepted Submission(s): 723


Problem Description
一把锁匙有N个槽,槽深为1,2,3,4。每锁匙至少有3个不同的深度且至少有1对相连的槽其深度之差为3。求这样的锁匙的总数。
 

Input
本题无输入
 

Output
对N>=2且N<=31,输出满足要求的锁匙的总数。
 

Sample Output
  
N=2: 0 N=3: 8 N=4: 64 N=5: 360 .. .. .. .. .. .. .. N=31: ... 注:根据Pku Judge Online 1351 Number of Locks或 Xi'an 2002 改编,在那里N<=16
 

Author
ecjtu_zhousc
 

Recommend
lcy
 

Statistic |  Submit |  Discuss |  Note


解法:首先不考虑至少要有三个不同深度条件,然后再排除掉只有1和4的情况。

AC代码:

#include <cstdio>

long long ans[32]={
0,0,0,8,64,360,1776,8216,
36640,159624,684240,2898296,
12164608,50687208,209961648,
865509848,3553389280,14538802248,
59313382032,241378013240,980200805824,
3973116354984,16078778126448,64978668500120,
262277950619296,1057528710767880,4260092054072400,
17147133531655928,68968784226289024,277229417298013800,
1113741009496217136,4472142617535586136};

int main()
{
    for(int i=2;i<=31;i++)
    {
        printf("N=%d: %lld\n",i,ans[i]);
    }
    return 0;
}



打表代码:

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])
#define mem(a,x)  memset(a,x,sizeof a)
#define ysk(x)  (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn= 31   ;
ll dp[maxn+3][5],ans[maxn+3];
ll fac[maxn+5];
void solve()
{

    fac[0]=1;
    for(int i=1;i<=maxn;i++)//计算2^i
    {
        fac[i]=fac[i-1]*2;
    }

//首先不考虑至少要有三个不同深度条件
    dp[1][1]=dp[1][2]=dp[1][3]=dp[1][4]=1;//dp[len][x]代表长度为len 且最后一个位置为x,并且没有高度差为3的种数
    ans[1]=0;//ans[len]代表长度为len,并且存在高度差为3的种数。
    for(int len=2;len<=maxn;len++)
    {
        ans[len]=ans[len-1]*4+ dp[len-1][1]+dp[len-1][4];
        ll sum=0;
        for1(j,4)
        {
           sum+=dp[len-1][j];
        }
        dp[len][1]=sum-dp[len-1][4];
        dp[len][4]=sum-dp[len-1][1];
        dp[len][2]=dp[len][3]=sum;

    }
//排除掉只有1和4的情况。
    for(int len=2;len<=maxn;len++)
    {
        ans[len]-=(fac[len]-2);
    }

}


int main()
{
   std::ios::sync_with_stdio(false);
   solve();
   freopen("out.txt","w",stdout);
   printf("ll ans[35]={\n");
   for(int i=0;i<=31;i++)
   {
       if(i)  putchar(',');
       printf("%lld",ans[i]);
   }
   printf("};\n");
   return 0;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值