洛谷 U88663 紧密数

U88663 紧密数

题目描述

给出一个数字表{0,1,2,---,k},1≤k≤9。可以用这个数字表构造出长度为n的数,如果所构造的这个数的任意两个相邻的数字差都不超过1,则称这个数为该数字表上的n紧凑数。如k=9,101010就是一个长度为6的紧密数。可以认为010101也是一个长度为6的紧密数。

输入格式

测试数据有多组。
每组一行包含两个整数k和n,之间用一个空格隔开。

输出格式

对输入的每一行,输出一个实数,表示长度为n的所有数中,紧密数所占的 百分比,保留小数点后5位。

输入输出样例 #1

输入 #1

4 1
2 5
3 5
8 7

输出 #1

100.00000
40.74074
17.38281
0.10130

说明/提示

1≤n≤100

题意

数字集合:(0,1,2,\dots,k),一共 (k+1) 种数字。

构造长度为 n 的序列(允许前导 0),如果相邻两个数字的差的绝对值 (\le 1),该序列称为紧密数。

求紧密数占全部序列的百分比,结果保留小数点后 5 位输出:

(\text{百分比}= \frac{\text{紧密数总个数}}{\text{总方案数}} \times 100)
总方案数:每个位置有 (k+1) 种选择,(\boldsymbol{total=(k+1)^n})。

数据范围:(1\le n \le 100),直接整数计数会溢出,使用double浮点 DP。

DP 设计

状态定义

(dp[i][j]):长度为 i,末尾数字为 j 的紧密数数量。

状态转移

dp[i][j]=dp[i-1][0]+dp[i-1][1] &j=0
dp[i-1][k-1]+dp[i-1][k] &j=k
dp[i-1][j-1]+dp[i-1][j]+dp[i-1][j+1] &0<j<k### 初始条件

长度为 1 时所有数字都合法:

(dp[1][j]=1,quad j=0,1,dots,k)

答案计算

dp[n][j]}{(k+1)^n

样例说明

  1. k=4,n=1:长度为 1 全部合法,输出 100.00000
  2. k=2,n=5:总方案 (3^5=243),紧密数共 99 个;
    (99 \div 243 \times100=40.74074)。

代码(c++):

#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
const int MAXN=105;
const int MAXK=10;
double dp[MAXN][MAXK];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int k,n;
    // 多组输入直到EOF
    while (cin>>k>>n){
        memset(dp,0,sizeof(dp));
        // 边界:长度为1,所有数字均合法
        for(int j=0;j<=k;++j){
            dp[1][j]=1.0;
        }
        // dp转移
        for(int i=2;i<=n;++i){
            for (int j=0;j<=k;++j){
                if(j==0) {
                    dp[i][j]=dp[i-1][0]+dp[i-1][1];
                }else if(j==k){
                    dp[i][j]=dp[i-1][k-1]+dp[i-1][k];
                }else{
                    dp[i][j]=dp[i-1][j-1]+dp[i-1][j]+dp[i-1][j+1];
                }
            }
        }
        double sum=0.0;
        for(int j=0;j<=k;++j){
            sum+=dp[n][j];
        }
        // 总方案数 (k+1)^n
        double total=1.0;
        for (int i=1;i<=n;++i){
            total*= (k+1);
        }

        double ans=sum/total*100.0;
        cout<<fixed<<setprecision(5)<<ans<<'\n';
    }
    return 0;
}
posted @ 2026-08-22 21:32  绪山_smile楽しい  阅读(8)  评论(0)    收藏  举报