[编程题] 小易喜欢的数列 dp
https://www.nowcoder.com/question/next?pid=6291726&qid=112729&tid=12736753
[编程题] 小易喜欢的数列
时间限制:1秒
空间限制:32768K
小易非常喜欢拥有以下性质的数列:
1、数列的长度为n
2、数列中的每个数都在1到k之间(包括1和k)
3、对于位置相邻的两个数A和B(A在B前),都满足(A <= B)或(A mod B != 0)(满足其一即可)
例如,当n = 4, k = 7
那么{1,7,7,2},它的长度是4,所有数字也在1到7范围内,并且满足第三条性质,所以小易是喜欢这个数列的
但是小易不喜欢{4,4,4,2}这个数列。小易给出n和k,希望你能帮他求出有多少个是他会喜欢的数列。
View Code
1、数列的长度为n
2、数列中的每个数都在1到k之间(包括1和k)
3、对于位置相邻的两个数A和B(A在B前),都满足(A <= B)或(A mod B != 0)(满足其一即可)
例如,当n = 4, k = 7
那么{1,7,7,2},它的长度是4,所有数字也在1到7范围内,并且满足第三条性质,所以小易是喜欢这个数列的
但是小易不喜欢{4,4,4,2}这个数列。小易给出n和k,希望你能帮他求出有多少个是他会喜欢的数列。
输入描述:
输入包括两个整数n和k(1 ≤ n ≤ 10, 1 ≤ k ≤ 10^5)
输出描述:
输出一个整数,即满足要求的数列个数,因为答案可能很大,输出对1,000,000,007取模的结果。
输入例子1:
2 2
输出例子1:
3
dp[i][j]表示第i个位置放的数是j的时候的合法方案是多少。
转移:dp[i - 1][j] = sigma(dp[i][1...j]) - (sigma(dp[i][j的因子]);
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; const int maxn = 1e5 + 20; const int MOD = 1e9 + 7; LL dp[2][maxn]; void add(LL &x, LL y) { x = (x + y + MOD) % MOD; } int prime[maxn][12]; void init_prime() { for (int i = 2; i <= maxn - 20; ++i) { if (prime[i][0]) continue; // 这个数i不是质数 for (int j = i; j <= maxn - 20; j += i) { prime[j][++prime[j][0]] = i; } //prime[12] = {2, 3} } } vector<int> vc[maxn]; void ca(int num, int to, int now) { if (now > num / 2) return; if (num % now == 0) vc[num].push_back(now); else return; if (to == 0) to = 1; for (int i = to; i <= prime[num][0]; ++i) { ca(num, i, now * prime[num][i]); } } void show() { int f = 18; for (int i = 0; i < vc[f].size(); ++i) { cout << vc[f][i] << " "; } cout << endl; } void work() { int n, k; cin >> n >> k; int now = 0; LL sum = k; for (int i = 1; i <= k; ++i) { dp[0][i] = 1; } init_prime(); for (int i = 1; i <= k; ++i) { ca(i, 0, 1); } // show(); for (int i = n - 1; i >= 1; --i) { now = !now; dp[now][1] = sum; for (int j = 2; j <= k; ++j) { dp[now][j] = sum; // for (int f = 2 * j; f <= k; f += j) { // add(dp[now][j], -dp[!now][f]); // } for (int f = 0; f < vc[j].size(); ++f) { add(dp[now][j], -dp[!now][vc[j][f]]); } } sum = 0; for (int j = 1; j <= k; ++j) { // sum[j] = dp[now][j]; // add(sum[j], sum[j - 1]); add(sum, dp[now][j]); } } LL ans = 0; for (int i = 1; i <= k; ++i) { add(ans, dp[now][i]); } cout << ans << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif work(); return 0; }
既然选择了远方,就要风雨兼程~
posted on 2017-12-08 15:20 stupid_one 阅读(530) 评论(0) 编辑 收藏 举报