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(1≤T≤100)表示样例个数。
对于每一个样例:
第一行两个整数n,k(1≤n,k≤105)n, k(1 \le n, k \le 10^5)n,k(1≤n,k≤105)。
数据保证∑n≤3×105\sum n \le 3 \times 10^5∑n≤3×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[kj≤i]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

912

被折叠的 条评论
为什么被折叠?



