钥匙计数之一
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
解法:首先不考虑至少要有三个不同深度条件,然后再排除掉只有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;
}