题意:
告诉你n,m,k。
让你构造k 个数, 使得他们的和为n , 最小公倍数是m, 求方案数?
思路:
本以为是一个数学, 是一个水dp。
我们直接按照他描述的建立状态。
令 dp[i][j][k] , 表示 目前选了i 个数, 和为j , 最小公倍数是k 的方案数。
那么转移方程就很好写了 dp[i+1][j + a][lcm(a, k)] += dp[i][j][k].
但是得优化一些地方。
1.首先空间上 , 这样是爆内存的, 把第一维改成滚动数组就行了。
第二个 , 时间上优化。
转移时候你得枚举上一个数是啥, 这一个数是啥 , 这样1000的方了。
我们知道 ,假如k 个数的最小公倍数是m 的话 , 那么这k个数都是m 的因子。
2.那这样就好办了。 我们先处理m 的因子数量(最多不超过50).
然后枚举因子进行转移就好了。 这就成了50的方了。
3.另外还可以加入一些小的优化。
因为转移到m 只需要因子, 那么不如把因子离散化一下。
这样内存就开到了 dp[2][1000][50].
4. 在一点就是 lcm 时候也比较慢, 不如预处理出来所有因子的lcm。 这样olog 变成了 o1
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m, k;
const int mod = 1000000000 + 7;
long long dp[2][1007][50];
int gcd(int a,int b){
return !b ? a :gcd(b, a%b);
}
int lcm(int a,int b){
return a*b / gcd(a,b);
}
int LCM[1007][1007];
int fac[1007];
int cnt = 0;
void add(long long& ans, long long x){
ans += x;
if (ans >= mod) ans -= mod;
}
int pos[1007];
int main(){
while(~scanf("%d %d %d",&n, &m, &k)){
for (int i = 0; i <= n; ++i){
for (int j = 0; j < 50; ++j){
dp[0][i][j] = 0;
}
}
cnt = 0;
for (int i = 1; i <= m; ++i){
if (m % i == 0) {
fac[cnt++] = i;
pos[i] = cnt-1;
dp[0][i][pos[i] ] = 1;
}
}
for (int i = 0; i < cnt; ++i){
for (int j = 0; j < cnt; ++j){
LCM[i][j] = lcm(fac[i], fac[j]);
}
}
for (int i = 1; i < k; ++i){
int second = (i & 1);
int first = second ^ 1;
for (int j = 0; j <= n; ++j){
for (int o = 0; o < 50; ++o){
dp[second][j][o] = 0LL;
}
}
for (int j = 0; j <= n; ++j){
for (int l = 0; l < cnt; ++l){
int f = fac[l];
if (dp[first][j][pos[f] ]){
for (int m = 0; m < cnt; ++m){
int f2 = fac[m];
if (j + f2 <= n)add(dp[second][j + f2][pos[LCM[l][m]] ] , dp[first][j][pos[f] ]);
}
}
}
}
}
printf("%I64d\n", dp[!(k & 1) ][n][pos[m] ]);
}
return 0;
}
Math Magic
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2133 Accepted Submission(s): 709
Problem Description
Yesterday, my teacher taught us about math: +, -, *, /, GCD, LCM... As you know, LCM (Least common multiple) of two positive numbers can be solved easily because of a * b = GCD (a, b) * LCM (a, b).
In class, I raised a new idea: “how to calculate the LCM of K numbers”. It's also an easy problem indeed, which only cost me 1 minute to solve it. I raised my hand and told teacher about my outstanding algorithm. Teacher just smiled and smiled...
After class, my teacher gave me a new problem and he wanted me solve it in 1 minute, too.
If we know three parameters N, M, K, and two equations:
1. SUM (A 1, A 2, ..., A i, A i+1,..., A K) = N
2. LCM (A 1, A 2, ..., A i, A i+1,..., A K) = M
Can you calculate how many kinds of solutions are there for A i (A i are all positive numbers).
I began to roll cold sweat but teacher just smiled and smiled.
Can you solve this problem in 1 minute?
In class, I raised a new idea: “how to calculate the LCM of K numbers”. It's also an easy problem indeed, which only cost me 1 minute to solve it. I raised my hand and told teacher about my outstanding algorithm. Teacher just smiled and smiled...
After class, my teacher gave me a new problem and he wanted me solve it in 1 minute, too.
If we know three parameters N, M, K, and two equations:
1. SUM (A 1, A 2, ..., A i, A i+1,..., A K) = N
2. LCM (A 1, A 2, ..., A i, A i+1,..., A K) = M
Can you calculate how many kinds of solutions are there for A i (A i are all positive numbers).
I began to roll cold sweat but teacher just smiled and smiled.
Can you solve this problem in 1 minute?
Input
There are multiple test cases.
Each test case contains three integers N, M, K. (1 <= N, M <= 1,000, 1 <= K <= 100)
Each test case contains three integers N, M, K. (1 <= N, M <= 1,000, 1 <= K <= 100)
Output
For each test case, output an integer indicating the number of solution modulo 1,000,000,007(10
9 + 7).
You can get more details in the sample and hint below.
You can get more details in the sample and hint below.
Sample Input
4 2 2 3 2 2
Sample Output
1 2HintThe first test case: the only solution is (2, 2). The second test case: the solution are (1, 2) and (2, 1).
Source
Recommend
zhuyuanchen520 | We have carefully selected several similar problems for you:
6032
6031
6030
6029
6028