DP(优化) UVALive 6073 Math Magic

/************************************************
* Author        :Running_Time
* Created Time  :2015/10/28 星期三 20:20:09
* File Name     :H.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e3 + 10;
const int M = 1e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-10;
const double PI = acos (-1.0);
int dp[2][N][N];
int lcm[N][N];
int vec[N];

int GCD(int a, int b)   {
    return b ? GCD (b, a % b) : a;
}

void init(void) {
    for (int i=1; i<=1000; ++i) {
        for (int j=1; j<=1000; ++j) {
            lcm[i][j] = i * j / GCD (i, j);
        }
    }
}

inline void add(int &x, int y)   {
    x += y;
    if (x > MOD)    x -= MOD;
}

int main(void)    {
    init ();
    int n, m, k;
    while (scanf ("%d%d%d", &n, &m, &k) == 3)   {
        int t = 0;
        for (int i=1; i<=m; ++i)    {
            if (m % i == 0) vec[t++] = i;
        }
        int now = 0;
        for (int i=0; i<=n; ++i)    {
            for (int j=0; j<t; ++j) {
                dp[now][i][vec[j]] = 0;
            }
        }
        dp[now][0][1] = 1;
        for (int l=1; l<=k; ++l)    {
            now ^= 1;
            for (int i=0; i<=n; ++i)    {
                for (int j=0; j<t; ++j) {
                    dp[now][i][vec[j]] = 0;
                }
            }
            for (int i=l-1; i<=n; ++i)  {
                for (int j=0; j<t; ++j) {
                    if (dp[now^1][i][vec[j]] == 0)   continue;
                    for (int p=0; p<t; ++p) {
                        int x = i + vec[p];
                        int y = lcm[vec[j]][vec[p]];
                        if (x > n || m % y != 0)    continue;
                        dp[now][x][y] = (dp[now][x][y] + dp[now^1][i][vec[j]]) % MOD;
                    }
                }
            }
        }
        printf ("%d\n", dp[now][n][m]);
    }

   //cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";

    return 0;
}

  

时间: 2024-08-26 15:59:15

DP(优化) UVALive 6073 Math Magic的相关文章

UVALive 6073 Math Magic

                                              6073 Math MagicYesterday, my teacher taught us about math: +, -, *, /, GCD, LCM... As you know, LCM (Leastcommon multiple) of two positive numbers can be solved easily because of a ∗ b = GCD(a, b) ∗ LCM(a

HDU 4427 Math Magic(三维dp)

题目大意:给你三个数n,m,k.表示有k个数,他们的和为n,k个数的最小公倍数是m.让你求出符合这个条件的k个数的序列有多少种. 一看以为是个数论题,还尝试这各种分解m,然后进行组合数求情况.但是组合出来的数没法做减法啊... 结果是道dp题目.i,j,k表示到了第i个数此时和为j,最小公倍数为k.已经有了多少种组合方法了,直接向后推就可以了啊.数组太大开不开啊,滚动一下就可以了啊. Math Magic Time Limit: 4000/2000 MS (Java/Others)    Mem

Math Magic(完全背包)

Math Magic Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description Yesterday, my teacher taught us about math: +, -, *, /, GCD, LCM... As you know, LCM (Least common multiple) of two positive numbers can b

树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

1 // 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree 2 // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以走多次,问从每个点出发的最大获益 3 // 思路: 4 // dp[i]: 从i点出发回到i点的最大值 5 // d[i][0] 从i点出发不回来的最大值 6 // d[i][1] 从i点出发取最大值的下一个点 7 // d[i][2] 从i点出发取次大值 8 // dfs1处理出这四个 9

常见的DP优化类型

常见的DP优化类型 1单调队列直接优化 如果a[i]单调增的话,显然可以用减单调队列直接存f[j]进行优化. 2斜率不等式 即实现转移方程中的i,j分离.b单调减,a单调增(可选). 令: 在队首,如果g[j,k]>=-a[i],那么j优于k,而且以后j也优于k,因此k可以重队列中直接删去.在队尾,如果x<y<z,且g[x,y]<=g[y,z],也就是说只要y优于x一定可以得出z优于y的,我们就删去y. 经过队尾的筛选,我们在队列中得到的是一个斜率递减的下凸包,每次寻找从上往下被-

hdu5009 离散化+dp+优化

西安网络赛C题.先对大数据离散化,dp优化 #include<iostream> //G++ #include<vector> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<cmath> using namespace std; const int maxn=512

LCIS tyvj1071 DP优化

思路: f[i][j]表示n1串第i个与n2串第j个且以j结尾的LCIS长度. 很好想的一个DP. 然后难点是优化.这道题也算是用到了DP优化的一个经典类型吧. 可以这样说,这类DP优化的起因是发现重复计算了很多状态,比如本题k的那层循环. 然后就可以用maxl标记搞一下,将O(n^3)变成O(n^2). #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> usi

loj6171/bzoj4899 记忆的轮廊(期望dp+优化)

题目: https://loj.ac/problem/6171 分析: 设dp[i][j]表示从第i个点出发(正确节点),还可以有j个存档点(在i点使用一个存档机会),走到终点n的期望步数 那么 a[i][k]表示i点为存档点,从i点走到k点(正确节点)的期望步数(中间没有其它存档点) 那么a[i][j]可以递推预处理出 其中g[v]表示从一个错误节点v开始走,期望走g[v]步会读档 解方程可以解出 s[j-1]就是点j-1出去的所有错误儿子的g[v]之和 那么接下来只要知道如何求g[v]就行了

poj1088 滑雪(dfs、dp优化)

#include <iostream> #include <map> #include <string> #include <cstdio> #include <sstream> #include <cstring> #include <vector> #include <cmath> #define N 110 int a,b,step=0; int anw=0; int moun[N][N]; int dp