题意:
有n个火柴棒,已知拼成9个数字花费的数目,求能拼出的能整除m的最大数
分析:
dp[i][j]表示,用i个火柴棒,拼出的数余m余数为j时的最大数
int tmp=dp[i][j]*10+k;(k是拼成的某个数)
dp[i+num[k]][tmp%m]=max(dp[i+num[k]][tmp%m],tmp);
这个数很大,用java写超时了两发,只能用大数模拟。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int n,m; struct bignum { int l; char a[60]; void zclear() { while (a[l-1]==0) l--; } void set(char v) { memset(a,0,sizeof(a)); l=1; a[0]=v; if (v==0) l=0; } void add(char v) { char i; a[0]+=v; for (i=0;i<l;++i) { if (a[i]>=10) { a[i+1]++; a[i]-=10; } else break; } if (a[l]>0) l++; zclear(); } void mul10() { for (int i=l;i>0;--i) a[i]=a[i-1]; a[0]=0; l++; zclear(); } bool bigger(bignum ta) { ta.zclear();zclear(); if (ta.l!=l) return l>ta.l; for (int i=l-1;i>=0;--i) if (ta.a[i]!=a[i]) return a[i]>ta.a[i]; } void give(bignum ta) { l=ta.l; memcpy(a,ta.a,sizeof(char)*60); } void output() { if (a[0]==-1||l==0) { if (n>=6) printf("0\n"); else printf("-1\n"); return; } for (int i=l-1;i>=0;--i) printf("%d",(char)a[i]); printf("\n"); } }; bignum dp[101][3003]; int num[10]={6,2,5,5,4,5,6,3,7,6}; int ca=0; int i,j,k; int main() { while (scanf("%d",&n),n) { scanf("%d",&m); for (i=1;i<=n;++i) for (j=0;j<m;++j) dp[i][j].set(-1); for (i=0;i<10;++i) dp[num[i]][i%m].set((char)i); for (i=1;i<=n;++i) for (j=0;j<m;++j) if (dp[i][j].a[0]!=-1) { for (k=0;k<10;++k) { int x=i+num[k]; int y=(j*10%m+k%m)%m; if (x>n) continue; bignum temp; temp.give(dp[i][j]); temp.mul10(); temp.add((char)k); if (temp.bigger(dp[x][y])) dp[x][y].give(temp); } } bignum minv; minv.set(-1); for (i=1;i<=n;++i) if (dp[i][0].bigger(minv)) minv.give(dp[i][0]); printf("Case %d: ",++ca); minv.output(); } return 0; }
原文:http://www.cnblogs.com/zsf123/p/4876157.html