题意:一个从开始到中间是非递减的回文被称为特殊回文,例如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; }