HDU 4427 Math Magic【dp+優化+滾動陣列】【好題】
Math Magic
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2084 Accepted Submission(s): 692
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 (A1, A2, ..., Ai, Ai+1,..., AK) = N
2. LCM (A1, A2, ..., Ai, Ai+1,..., AK) = M
Can you calculate how many kinds of solutions are there for Ai (Ai 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 (A1, A2, ..., Ai, Ai+1,..., AK) = N
2. LCM (A1, A2, ..., Ai, Ai+1,..., AK) = M
Can you calculate how many kinds of solutions are there for Ai (Ai 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(109 + 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
2
Hint
The first test case: the only solution is (2, 2).
The second test case: the solution are (1, 2) and (2, 1).
Source
dp[i][j][k]。表示長度為i。和為j。最小公倍數為k的方法數。設a為解的第i+1個數。
那麼狀態轉移就為
dp[i+1][j+a][lcm(a,k)]+=dp[i][j][k]。lcm為最大公倍數。
因為開不了那麼大的陣列,因此要用滾動陣列。
為了節約時間先預處理出1000以內任意兩數的最小公倍數。
同時在迴圈的時候要注意剪枝(if (dp[(j-1)&1][i][last] == 0) continue;//如果上一狀態為0則不用計算上一步)
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<bitset>
#include<numeric>
#include<vector>
#include<string>
#include<iterator>
#include<cstring>
#include<functional>
#define INF 0x3f3f3f3f
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 10010;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
typedef pair<int, int> P;
typedef long long ll;
typedef unsigned long long ull;
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
}
int lcm(int a, int b)
{
return a / gcd(a, b) * b;
}
int N, M, n;
int dp[2][1000 + 5][1000 + 5];
int LCM[1000 + 5][1000 + 5];
int fac[1000 + 5];
int main()
{
for (int i = 1; i <= 1000; i++)
{
for (int j = i; j <= 1000; j++)
{
LCM[i][j] = LCM[j][i] = lcm(i, j);
}
}
while (scanf("%d %d %d", &N, &M, &n) != EOF)
{
int cnt = 0;
for (int i = 1; i <= M; i++)
{
if (M%i == 0) fac[cnt++] = i;
}
ms(dp, 0);
for (int i = 0; i < cnt; i++)
{
dp[0][fac[i]][fac[i]] = 1;
}
for (int j = 1; j < n; j++) //當前選的數 從j推j+1 故只需要推到n-1
{
ms(dp[j & 1], 0);
for (int i = j; i <= N; i++)//列舉和 j最小為1所以和最小隻可能為1
{
for (int k = 0; k < cnt; k++)//列舉上一狀態公倍數
{
int last = fac[k];
if (dp[(j-1)&1][i][last] == 0) continue;//如果上一狀態為0則不用計算上一步
for (int p = 0; p < cnt; p++)//列舉公因子
{
int cur = fac[p];
if (i+cur<=N)//保證i+cur在範圍內
dp[j & 1][i + cur][LCM[last][cur]] = (dp[j & 1][i + cur][LCM[last][cur]] + dp[(j-1)&1][i][last]) % 1000000007;
}
}
}
}
printf("%d\n", dp[(n-1)& 1][N][M]);
}
}
相關文章
- HDU - 6182 A Math Problem
- HDU 3183 A Magic Lamp (RMQ)LAMPMQ
- 演算法基礎:動態規劃陣列中滾動陣列的使用演算法動態規劃陣列
- JS陣列專題1️⃣ ➖ 陣列扁平化JS陣列
- HDU 6063 RXD and math (打表)
- HDU 5816 Hearthstone(狀態壓縮DP+概率)
- HDU 5862 Counting Intersections(樹狀陣列+掃描線+離散化)陣列
- HDU 1541 & POJ 2352 Stars (樹狀陣列)陣列
- 序列(dp+矩陣加速)矩陣
- hdu 1277 AC自動機入門(指標版和陣列版)指標陣列
- HDU 2689 Sort it【樹狀陣列求逆序對】陣列
- 每日 30 秒 ⏱ 優雅初始化陣列陣列
- iOS11 標題滾動變化iOS
- HDU 1556 Color the ball(線段樹|樹狀陣列)陣列
- 幸運數(dp+矩陣加速)矩陣
- 巨大的數(dp+矩陣加速)矩陣
- 【dp+組合數學】hdu 2018 多校第九場 1001 Rikka with Nash Equilibrium hdu 6415UI
- KMP演算法以及優化(程式碼分析以及求解next陣列和nextval陣列)KMP演算法優化陣列
- bzoj 4899 記憶的輪廓 題解(概率dp+決策單調性優化)優化
- 陣列題目陣列
- 陣列 題目陣列
- 2-7 陣列:動態陣列陣列
- [JAVA] Java 陣列、多維陣列,動態、靜態初始化,陣列JVM記憶體模型分析Java陣列JVM記憶體模型
- 陣列去重和陣列扁平化陣列
- HDU 6274 Master of Sequence(思維+樹狀陣列+二分)AST陣列
- HDU 1556【區間更新+單點查詢 樹狀陣列】陣列
- 動態陣列陣列
- 陣列004 動態建立一維陣列陣列
- 【基礎題】【陣列】定義並初始化陣列
- 陣列扁平化陣列
- php陣列問題PHP陣列
- LeetCode刷題—陣列LeetCode陣列
- HDU1166 敵兵佈陣【樹狀陣列 單點修改+區間查詢】陣列
- Java陣列如何實現動態初始化Java陣列
- vue中陣列變動不被監測問題Vue陣列
- leetcode題解(陣列問題)LeetCode陣列
- web前端陣列處理之扁平化陣列Web前端陣列
- 使用 CSS Scroll Snap 優化滾動,提升使用者體驗!CSS優化
- 直播app系統原始碼,css優化滾動條樣式APP原始碼CSS優化