【8月刷题打卡】四方定理

57 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

四方定理

题目描述

四方定理是众所周知的:任意一个正整数nn,可以分解为不超过四个整数的平方和。例如:25=12+22+22+4225=1^{2}+2^{2}+2^{2}+4^{2},当然还有其他的分解方案,25=42+3225=4^{2}+3^{2}25=5225=5^{2}。给定的正整数nn,编程统计它能分解的方案总数。注意:25=42+3225=4^{2}+3^{2}25=32+4225=3^{2}+4^{2}视为一种方案。

输入格式

第一行为正整数tt(t100t\le 100),接下来tt行,每行一个正整数nn(n32768n\le 32768)。

输出格式

对于每个正整数nn,输出方案总数。

样例 #1

样例输入 #1

1
2003

样例输出 #1

48

解题思路

就是一个背包,把每个平方数看成一个物品,求方案数。 因为对用的数的个数有要求,所以是二维费用背包,要注意的是每个数是不限个数的。

先构造a[i],就是平方数,这是物品大小,n就是背包大小,设f[i]表示背包大小为i能装满的方案

核心如下:

for (int i=1;i<=物品总数;i++)
       for (int j=a[i];j<=背包最高价值;j++)
          f[j]+=f[j-a[i]];

f[][]的第二维就是平方数的个数,在解决了方案总数怎么求之后,就要考虑只能用四个或四个以下。所以要加一维。

总结为f[j][k]代表价值上线为j,取k个数作组合时的方案总数。则最后答案为f[n][1]到f[n][4]的和。

#include<bits/stdc++.h>
using namespace std;
int a[185],f[32770][5],m,n;
int main()
{   for(int i=1;i<=181;i++)
    a[i]=i*i;             
    f[0][0]=1; 
    for (int i=1;i<=181;i++)
       for (int j=a[i];j<=32768;j++)
          for(int k=1;k<=4;k++)
          f[j][k]+=f[j-a[i]][k-1];
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>m;
        cout<<f[m][1]+f[m][2]+f[m][3]+f[m][4]<<endl;
    }
    return 0;
}