zoukankan      html  css  js  c++  java
  • 洛谷p1586四方定理题解

    题目

    这个题的本质是动态规划中的背包问题。

    为什么会想到背包呢。

    因为往往方案数不是排列组合就是递推或者是dp,当然还有其他的可能。我们可以把一个数的代价当成这个数的平方,价值就是一个方案数。由于这个数可以取无数次所以这个背包问题即为一个完全背包。  因此我们可以预处理出从1到数据范围的所有数的方案。

    这个过程也是一个DP的过程。我们先把1到sqrt(数据范围)的数的平方数存到data数组中。然后再套用背包公式

    因为最大的平方数是32768.所以最大的数是181.因此我们可以想象成共有181个物品。每个人所占的价值为data[i]。因为是四个二次方数。我们可设一个二维数组dp[i][j]表示数i在取j个平方数的时候的方案数。

    因此我们可以得到状态转移方程。

    for(int j=1;j<=181;j++)

    for(int k=1;k<=32786;k++)

    for(int i=1;i<=4;i++)

    dp[当前的数][当前取平方数的个数]+=dp[当前的数-data[i]][当前取平方数的个数-1]

    (dp[k][i]+=dp[k-data[i]][i-1];) 

    预处理完之后,这个题就结束了。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int t,data[182],sum,dp[35000][5];
    int main()
    {
        dp[0][0]=1;
        for(int i=1;i<=181;i++)
            data[i]=i*i;
        for(int i=1;i<=181;i++)
          for(int j=data[i];j<=32768;j++)
            for(int k=1;k<=4;k++)
          {
              dp[j][k]+=dp[j-data[i]][k-1];
          }    
        scanf("%d",&t);
        while(t--)
        {
            int x,ans=0;
            scanf("%d",&x); 
            for(int i=1;i<=4;i++)
            {
                ans+=dp[x][i];
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    组合数据类型练习
    词法分析
    ORACLE聚合函数细节
    Centos7 最小系统安装Redis
    JQuery版评分控件
    Javascript & JQuery读书笔记
    HTML5&CSS3读书笔记
    Javascript版显示相应图片的详细信息
    MVC2,MVC3,MVC4和MVC5的不同
    Microsoft Office Excel cannot access the file
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/9215083.html
Copyright © 2011-2022 走看看