您的位置:首页 > 其它

HDU 1133

2012-12-07 18:34 162 查看
这道题目我用dp过了,转化了思路,把50元准换为1步的长度,把100元转换成2步的步长,总长度为n+2*m

这个思路也不知道就蹦出来了,嘿嘿,很特别吧,兮兮~~

开始的时候直接超内存了开了1200w+的数组,最后压缩成300w+ ,进制提高了

可能速度不是很快31ms,但还是挺有成就感,利用了大数乘大数

#include<iostream>
using namespace std;

//用到大数
const int MAX=102;//最大的位数

//设50的步数是1,设100的步数是2
int dp[101][301][MAX];//dp[i][j] i个1步,总步数是j,后面的维数存放大数

inline void Add(int c[],int a[],int b[])//c=a+b 大数加大数
{
int temp=0;//进位
for (int i=MAX-1;i>=0;i--)
{
c[i]=a[i]+b[i]+temp;
temp=c[i]/10000;
c[i]%=10000;
}
}

inline void Imul(int c[],int n,int a[])// c=n*a;一个数乘以一个大数
{
int temp=0;
for (int i=MAX-1;i>=0;i--)
{
c[i]=a[i]*n+temp;
temp=c[i]/10000;
c[i]%=10000;
}
}

inline void Ibigmul(int c[],int a[],int b[])//大数*大数
{
int z=-1;
for (int i=MAX-1;i>=0;i--)//b的第几位
{
z++;
int temp=0;
for (int j=MAX-1;j>=z;j--)//a的第几位
{
c[j-z]+=b[i]*a[j]+temp;
temp=c[j-z]/10000;
c[j-z]%=10000;
}
}
}

void Run()
{
memset(dp,0,sizeof(dp));
int i,j;
for (i=1;i<=100;i++)//一步的步数
{
for (j=i;3*i>=j&&j<=300;j++)
{
if(i==j)
{
dp[i][j][MAX-1]=1;//个位是1
continue;
}
//dp[i][j]=dp[i][j-2]+dp[i-1][j-1];
Add(dp[i][j],dp[i][j-2],dp[i-1][j-1]);
}
}
}

int temp_va[101][MAX];//保存n!
void Temp_va()
{
temp_va[0][MAX-1]=1;
for(int i=1;i<101;i++)
{
//temp_va[i]=i*temp_va[i-1];
Imul(temp_va[i],i,temp_va[i-1]);
}
}

int main()
{
int n,m,sum;
Run();
Temp_va();

int icase=1;
int ans[MAX],ians[MAX];
while(scanf("%d%d",&n,&m)!=EOF&&(n!=0||m!=0))
{
printf("Test #%d:\n",icase++);
if(n<m)
{
printf("0\n");
continue;
}
memset(ians,0,sizeof(ians));
memset(ans,0,sizeof(ans));
sum=n+2*m;
//dp
[sum]*temp_va
*temp_va[m];下面只是完成这个功能
Ibigmul(ians,temp_va
,temp_va[m]);
Ibigmul(ans,dp
[sum],ians);
bool flag=true;
for(int i=0;i<MAX;i++)
{
if(ans[i]==0&&flag) continue;
if(ans[i]/10==0&&!flag) printf("000");
else if(ans[i]/100==0&&!flag) printf("00");
else if(ans[i]/1000==0&&!flag) printf("0");
flag=false;

printf("%d",ans[i]);
}
putchar('\n');
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: