[小白算法入门] E.夜游江滩 算法题解

StarryCoding入门教育赛 3
比赛链接:https://www.starrycoding.com/contest/8

题目描述

eee宝和桶子晚上吃太饱没事做决定到江边散步减肥,他们在江滩的起始点(位置为000),要走到江滩的尽头(位置为nnn),由于他们腿特别长,一步可以走1,k,k2,k3...1,k,k^2,k^3...1,k,k2,k3...的距离,他们想知道走到尽头一共有多少种走法。

最后的结果对109+710^9+7109+7取模。

输入格式

第一行一个整数T(1≤T≤100)T(1 \le T \le 100)T(1T100)表示样例个数。

对于每一个样例:

第一行两个整数n,k(1≤n,k≤105)n, k(1 \le n, k \le 10^5)n,k(1n,k105)

数据保证∑n≤3×105\sum n \le 3 \times 10^5n3×105

输出格式

对于每组测试样例,一个整数表示结果。

输入样例1

2
3 2
5 3

输出样例1

3
4

解释

对于第二组样例,有{1,1,3},{1,3,1},{3,1,1},{1,1,1,1,1}\{1, 1, 3\}, \{1, 3, 1\}, \{3, 1, 1\}, \{1, 1, 1, 1, 1\}{1,1,3},{1,3,1},{3,1,1},{1,1,1,1,1}四种走法。

题解

这是一道dp题。

定义dp[i]dp[i]dp[i]表示从000走到iii的方案数。

初始化dp[0]=1dp[0] = 1dp[0]=1

状态转移方程为:dp[i]=∑j=0[kj≤i]dp[j]dp[i] = \sum_{j=0}[k^j \le i]dp[j]dp[i]=j=0[kji]dp[j]

最后输出dp[n]dp[n]dp[n]

每次转移时间复杂度为O(log(i))O(log(i))O(log(i)),于是总复杂度为O(nlogn)O(nlogn)O(nlogn)

注意特判k=1k = 1k=1的情况。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 9;
ll dp[N];
const ll p = 1e9 + 7;

void solve()
{
    int n, k;
    cin >> n >> k;
    if(k == 1)
    {
        cout << 1 << '\n';
        return;
    }
    dp[0] = 1;
    for (int i = 1; i <= n; ++i)
    {
        dp[i] = 0;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (ll j = 1; j <= i; j *= k)
        {
            dp[i] = (dp[i] + dp[i - j]) % p;
        }
    }
    cout << dp[n] << "\n";
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _;
    cin >> _;
    while (_--)
        solve();
    return 0;
}

StarryCoding是面向计算机专业学生的综合学习与刷题平台,平均每2-3天举办一场面向算法小白的入门教育赛,非常适合零基础的同学学习!
bing搜索:StarryCoding
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值