zoukankan      html  css  js  c++  java
  • 【DP】【P1586】四方定理

    传送门

    Description

    Input

    第一行为一个整数T代表数据组数,之后T行每行一个数n代表要被分解的数

    Output

    对于每个n输出一行,为方案个数

    Sample Input

    2
    2003
    25

    Sample Output

    2
    3

    Hint

    t<=100,n<=23768。

    Solution

      dp方程转移之类显然,唯一需要说的是有关去重的问题。显然需要打一张到maxn的平方表。然后f[i][j]代表i分解为j个平方数的方案数。如题面所说,x=a2+b2与x=b2+a2是同一种方案。既然如此,就不能外层循环第一维度内层循环平方表进行转移,因为这样在枚举了第一种方案后会继续枚举相同的第二种方案。考虑阶段:对于一个数x,它的分解方式可分为两个类,第一种是包含a2的,第二种是不包含a2的。对于这两个类分别枚举转移,则不会产生重复。正确性显然。故正确的枚举顺序是外层为平方表,内层是数字x,第三层是分解个数k。

    Code

    #include<cstdio>
    #define maxn 40000
    #define maxk 32769
    
    inline void qr(int &x) {
        char ch=getchar();int f=1;
        while(ch>'9'||ch<'0')    {
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')    x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x*=f;
        return;
    }
    
    inline int max(const int a,const int b) {if(a>b) return a;else return b;}
    inline int min(const int a,const int b) {if(a<b) return a;else return b;}
    inline int abs(const int x) {if(x>0) return x;else return -x;}
    
    inline void swap(int &a,int &b) {
        int c=a;a=b;b=c;return;
    }
    
    const int biao[]={0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400,441,484,529,576,625,676,729,784,841,900,961,1024,1089,1156,1225,1296,1369,1444,1521,1600,1681,1764,1849,1936,2025,2116,2209,2304,2401,2500,2601,2704,2809,2916,3025,3136,3249,3364,3481,3600,3721,3844,3969,4096,4225,4356,4489,4624,4761,4900,5041,5184,5329,5476,5625,5776,5929,6084,6241,6400,6561,6724,6889,7056,7225,7396,7569,7744,7921,8100,8281,8464,8649,8836,9025,9216,9409,9604,9801,10000,10201,10404,10609,10816,11025,11236,11449,11664,11881,12100,12321,12544,12769,12996,13225,13456,13689,13924,14161,14400,14641,14884,15129,15376,15625,15876,16129,16384,16641,16900,17161,17424,17689,17956,18225,18496,18769,19044,19321,19600,19881,20164,20449,20736,21025,21316,21609,21904,22201,22500,22801,23104,23409,23716,24025,24336,24649,24964,25281,25600,25921,26244,26569,26896,27225,27556,27889,28224,28561,28900,29241,29584,29929,30276,30625,30976,31329,31684,32041,32400,32761};
    int t,frog[maxn][5],a;
    
    inline int sigma(int a) {return frog[a][1]+frog[a][2]+frog[a][3]+frog[a][4];}
    
    int main() {
        qr(t);
        frog[0][0]=1;
        for(int i=1;i<=181;++i) {
            for(int j=biao[i];j^maxk;++j) {
                for(int k=1;k^5;++k) frog[j][k]+=frog[j-biao[i]][k-1];
            }
        }
        do {
            a=0;qr(a);printf("%d
    ",sigma(a));
        } while(--t);
        return 0;
    }

    Summary

      对于需要去重的方案个数DP,可以考虑将一个状态分解为包括一个元素的状态和不包括一个元素的状态,以被包括的元素做阶段进行转移,则不存在重复问题。

  • 相关阅读:
    UVa 12174 (滑动窗口) Shuffle
    UVa 1607 (二分) Gates
    CodeForces ZeptoLab Code Rush 2015
    HDU 1525 (博弈) Euclid's Game
    HDU 2147 (博弈) kiki's game
    UVa 11093 Just Finish it up
    UVa 10954 (Huffman 优先队列) Add All
    CodeForces Round #298 Div.2
    UVa 12627 (递归 计数 找规律) Erratic Expansion
    UVa 714 (二分) Copying Books
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/9179691.html
Copyright © 2011-2022 走看看