给定一个数,要求你求出将其拆分成任意个回文数有多少种方式。(回文数:如131,22,114411),n<40000。
思路:先求出40000以内的回文数,然后就是数的拆分问题,状态转移方程为
if(y>=回文数)
dp[x][y]=(dp[x][y-回文数]+dp[x-1][y]);//dp[x][y]代表y拆成前x种回文数的方式
else
dp[x][y]=dp[x-1][y];
注意取模
AC代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll mod = 1e9 + 7;
ll t, n,cmp=0;
ll dp[505][40500]; // dp[i][j]代表以j分解成前i种树有多少种方式
ll a[505];
int f(int x){
ll op[6],cnt=0;
while(x){
cnt++;
op[cnt]=x%10;
x/=10;
}
ll l=1,r=cnt,flag=1;
while(r>l){
if(op[l]!=op[r]){
flag=0;
break;
}
r--,l++;
}
return flag;
}
int main() {
cin >> t;
for(ll x=1;x<=40000;x++){
if(f(x)){
cmp++;
a[cmp]=x;
// cout<<a[cmp]<<" ";
}
}
dp[0][0]=1;
for(ll x=1;x<=cmp;x++){
dp[x][0]=1;
}
for(ll x=1;x<=cmp;x++){
for(ll y=1;y<=40000;y++){
if(y>=a[x])
dp[x][y]=(dp[x][y-a[x]]+dp[x-1][y])%mod;
// cout<<x<<" "<<y<<" "<<dp[x][y]<<endl;
else
dp[x][y]=dp[x-1][y];
}
}
while (t--) {
cin >> n;
cout<<dp[cmp][n]<<endl;
}
return 0;
}