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,可以考虑将一个状态分解为包括一个元素的状态和不包括一个元素的状态,以被包括的元素做阶段进行转移,则不存在重复问题。

  • 相关阅读:
    solr7之solrJ的使用
    solr7.3.1在CentOS7上的安装
    nginx配置:location配置方法及实例详解
    [读书]10g/11g编程艺术深入体现结构学习笔记(持续更新...)
    liunx系统计划任务管理(at/crond调度)
    Golden Gate 概念和机制
    Oracle三大经典表连接适用情况
    Oracle索引简单介绍与示例
    Oracle RAC的日志体系
    Oracle10g RAC的简单操作
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/9179691.html
Copyright © 2011-2022 走看看