zoukankan      html  css  js  c++  java
  • hdu 4427 Math Magic

    dp[i][j][k]为i个数,和为j,最小公倍数为k,满足的个数。

    dp[i+1][j+v][ lcm[k][v] ]+=dp[i][j][k]

    4层for循环,枚举i,j,k,v,朴素肯定超时,加上优化。

    首先可以预处理1000以内每两个数的最小公倍数。

    其次,枚举v的时候,只需要枚举m的因子就够了,因为他们要构成最小公倍数为m,必须每个数都是m的因子。这样的话k和j的枚举都降到很小了。

    由于100*1000*1000的int开不下,观察转移方程,i+1只和i有关,所以可以采用滚动数组。

    不加上面的优化,很容易超时。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define MOD 1000000007
    int lcm[1005][1005];
    int dp[2][1005][1005];
    int v[105];
    inline int gcd(int a,int b)
    {
        return a%b==0?b:gcd(b,a%b);
    }
    int main()
    {
        int n,m,k;
        for(int i=1;i<=1000;i++)
            for(int j=1;j<=1000;j++)
                if(!lcm[i][j]) lcm[j][i]=lcm[i][j]=i/gcd(i,j)*j;
        while(scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
            int top=0,tmp=sqrt(m*1.0);
            for(int i=1;i<=tmp;i++)
            {
                if(m%i==0) {
                    v[top++]=i;
                    if(i!=m/i)
                        v[top++]=m/i;
                }
            }
            sort(v,v+top);
            for(int i=0;i<=n;i++)
            memset(dp[0][i],0,sizeof(dp[0][i])),
            memset(dp[1][i],0,sizeof(dp[1][i]));
            for(int i=0;i<top;i++) dp[0][v[i]][v[i]]=1;
            int t=0;
            for(int i=1;i<k;i++)   //i个数
            {
                for(int ii=i;ii<=n;ii++)
                    for(int jj=0;jj<top;jj++)
                        dp[t^1][ii][v[jj]]=0;
                for(int j=i;j<n;j++)   //和为j
                    for(int w=0;w<top;w++) //最小公倍数为v[w]
                    {
                        if(dp[t][j][v[w]])
                        for(int s=0;j+v[s]<=n&&s<top;s++)  //最后一个数为v[s]
                        {
                            dp[t^1][j+v[s]][ tmp=lcm[v[w]][v[s]] ]+=dp[t][j][v[w]];
                            dp[t^1][j+v[s]][tmp]%=MOD;
                        }
                    }
                t^=1;
            }
            printf("%d
    ",dp[t][n][m]);
        }
        return 0;
    }
    


  • 相关阅读:
    mysql 常用命令
    MAC 升级到10.10(OS X Yosemite)下apache+php的配置问题
    php 第1讲 html介绍 html运行原理①
    php 开山篇
    Sublime Text 2
    java 抽象类和接口整理
    petri 网理论与研究(第一节140915)
    程序员应该读的书
    python logging模块小记
    常见设计模式,单例模式(双重检测锁方式)示例
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3278121.html
Copyright © 2011-2022 走看看