2015 HIAST Collegiate Programming Contest H

Special Palindrome

题意:一个从开始到中间是非递减的回文被称为特殊回文,例如1123211,定义F(N)为和为N的特殊回文的个数,如F(1)=1,即和为1的回文只有一个 就是 1,F(5)=7, (7), (1 5 1), (2 3 2), (1 1 3 1 1), (1 1 1 1 1 1 1),求F(N),N小于等于250

思路:当N为偶数时,分2种情况,第一种为回文的长度为奇数,那么,最中间的数 m 一定是2 4 6 8......两边的数的和为(N-m)>>1,对(N-i)>>1进行整数划分(m划分),第二种为回文长度为偶数,则回文两边的和为N>>1,对N>>1整数划分(N>>1划分),当N为奇数的时候只有一种情况,就是回文长度为奇数,最中间的数m为1 3 5 7....划分和上面一样

AC代码:

#include "iostream"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#define ll long long
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a) memset(a,0,sizeof(a))
#define mp(x,y) make_pair(x,y)
using namespace std;
const long long INF = 1e18+1LL;
const int inf = 1e9+1e8;
const int N=1e5+100;

///2015 HIAST Collegiate Programming Contest

///HHHH

ll dp[300][300];
void fun(int n){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            if(i==1||j==1) dp[i][j] = 1;
            else if(i>j) dp[i][j] = dp[i-j][j]+dp[i][j-1];
            else if(i == j) dp[i][j] = dp[i][i-1]+1;
            else dp[i][j] = dp[i][i];
    }
}
ll n,m,ans=0;
int main(){
    fun(251);
    while(cin>>n){
        if(n==0) return 0;
        ans=0;

        if(n&1){
            for(int i=1; i<=n; i+=2){
                ans+=dp[(n-i)/2][i];
            }
            ans++;
        }
        else{
            for(int i=2; i<=n; i+=2){
                ans+=dp[(n-i)/2][i];
            }
            ans+=dp[n/2][n/2];
            ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/max88888888/p/7162610.html