题目:https://www.luogu.org/problemnew/show/P1018
区间DP+高精,注意初始化和转移的细节。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #define MAXN 20005 using namespace std; typedef long long ll; ll n,k,a[45],f[45][7][MAXN],tmp[MAXN],num[MAXN]; char dc[45]; void nm(ll l,ll r) { // printf("l=%lld r=%lld\n",l,r); num[0]=r-l+1; for(ll i=l;i<=r;i++)//正存即可 num[i-l+1]=a[i]; // for(int i=1;i<=num[0];i++)printf("%lld",num[i]); // cout<<endl; } void init() { a[0]=strlen(dc); for(ll i=1;i<=a[0];i++) { a[i]=dc[a[0]-i]-‘0‘; // memset(num,0,sizeof num); // nm(1,i); memcpy(f[i][0],f[i-1][0],sizeof f[i-1][0]);//注意初始化! f[i][0][0]++;f[i][0][i]=a[i]; } } void ch(ll a[],ll b[]) { tmp[0]=a[0]+b[0]-1; for(ll i=1;i<=a[0];i++) for(ll j=1;j<=b[0];j++) { tmp[i+j-1]+=a[i]*b[j]; tmp[i+j]+=tmp[i+j-1]/10; tmp[i+j-1]%=10; } if(tmp[tmp[0]+1])tmp[0]++; } bool com(ll a[],ll b[]) { if(a[0]>b[0])return 1; if(a[0]<b[0])return 0; for(ll i=a[0];i;i--) { if(a[i]>b[i])return 1; if(a[i]<b[i])return 0; } return 0; } void print(ll a[]) { for(ll i=a[0];i;i--) printf("%lld",a[i]); } int main() { scanf("%lld%lld",&n,&k); cin>>dc; init(); // f[1][1][0]=1;f[1][1][1]=1; for(ll i=2;i<=n;i++) for(ll l=1;l<=min(i-1,k);l++) for(ll j=l;j<i;j++)//从l开始!!! { // f[i][l]=max(f[j][l-1]*num(j+1,i),f[i][l]); memset(tmp,0,sizeof tmp); memset(num,0,sizeof num); nm(j+1,i); ch(f[j][l-1],num); if(com(tmp,f[i][l]))memcpy(f[i][l],tmp,sizeof tmp); } print(f[n][k]); return 0; }