蓝桥杯C语言 算法训练 K好数(取模运算定理&&动态方程)

问题:
如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。
在这里插入图片描述
这道题让我们输出取模后的值
根据模的分配里率可知:
(a + b) mod n = [(a mod n) + (b mod n)] mod n
ab mod n = [(a mod n)(b mod n)] mod n

所以这道题我们应该每步取模,最后再模一次。

但是这道题的具体步骤需要用动态方程来解决。
意思是这道题不能一开始就想着结果,而是要先求过程量,看一下每一步的规律。
我们将4进制2位K好数和3位K好数的结果列出:(第一位数->K好数)
2位:1->2 2->2 3->3
3位:1->5 2->5 3->8
我们可以发现3位中第一位数是1的K好数数量等于第二位1和3的K好数数量之和。(而1和3刚好是满足第三位初始值为1时的第二位可取的值11x,13x)
这是不是意味着位数加一位后的K好数值和上一位有关,我可以根据这点,设第L位,从2位一直将K好数的值加到第L位,这样我们就知道了第L位的K好数数量:

   for(i=2;i<=l;i++)
            for(j=0;j<k;j++)//第i层0~k循环 
                for(x=0;x<k;x++)//第i-1层满足条件的数
                    if(x!=j-1&&x!=j+1)
                    {
                        dp[i][j]+=dp[i-1][x];//累计符合方案数 
                        dp[i][j]%=mod;//每次取模比最后取模好 
                    }`

上面代码中最难理解的一点是dp[i][j]+=dp[i-1][x]。
其实这句代码表达的意思是每一位中某个数的K好数都等于其上一位中满足条件(x!=j-1&&x!=j+1)的数的K好数之和。
然后代码层层递推从第二位数一直加到第L位。

另外当L=1时 是特殊情况,每一个数都是一个K好数,我们需要提前设置好这一点:

for(i=0;i<k;i++)
   dp[1][i]=1; //单独考虑 L=1 位时候的情况`

完整代码如下:


#include <stdio.h>					//AC码——Accept 
    #define mod 1000000007
    int main()
    {
    	int dp[105][105]={0};//初始化dp数组     105——数量级在100以内 
    	int k,l;//进制 k 位数 l  
    	int i,j,x;
        scanf("%d%d",&k,&l);
        for(i=0;i<k;i++)
            dp[1][i]=1; //单独考虑 L=1 位时候的情况
        for(i=2;i<=l;i++)
            for(j=0;j<k;j++)//第i层0~k循环 
                for(x=0;x<k;x++)//第i-1层满足条件的数
                    if(x!=j-1&&x!=j+1)
                    {
                        dp[i][j]+=dp[i-1][x];//累计符合方案数 
                        dp[i][j]%=mod;//每次取模比最后取模好 
                    }
    	int sum=0;
        for(i=1;i<k;i++)
        {
            sum+=dp[l][i];//所有方案数加起来 
            sum%=mod;//最后取模 
        }
    	printf("%d\n",sum);
    	return 0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值