很久没有写博客了呢。
今天来补一补。
ps:
要摆脱题解依赖了!
∑(っ °Д °;)っ (๑•̀ㅂ•́)و✧
先说这道dp方程十分简单,却要写高精的题。
这个dp【i】表示的是深度小于等于i的数目。所以最后结果需要剪掉它
找了一个重载运算符的代码。感觉真是异常的高深。学到了很多东西。
然后代码比别人写的短哈哈哈
再补充一句:
自己的一些小理解:
高精就是把一个数的每一位当成一个单独的字符进行运算,他们之间的唯一联系就在于进位。
而此题由于数很多。我们把三个字符砍成一截进行存储。所以就有了%1000这种东西。
其实本nc宝宝 一开始就有点翻不过来,尤其是到输出还有倒着输出。
但是后来你想想就明白了在单个的一节中 我们读肯定是 百十个、
输出顺序也是百十个。但是你的n节从左往右开始递增意思是右边最大。
先从右开始,在每个节中输出又是从做开始的所以正好啊。
!还有一点要注意的是每个字节都要沾满3个字符,不够就先补0
/**************************************************************
Problem: 1089
User: mars_ch
Language: C++
Result: Accepted
Time:36 ms
Memory:1476 kb
****************************************************************/
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rad 1000
//by mars_ch
using namespace std;
int n,d;
struct data
{
int l;
int v[5005];
}dp[31];
data operator*(data a,data b) //重新定义乘法的算法
{
data ans;
for(int i=1;i<=a.l+b.l;i++) ans.v[i]=0; //!!!!!! 没进行一会新的乘法,不能够累加上上回的结果
for(int i=1;i<=a.l;i++)
{
for(int j=1;j<=b.l;j++)
{
ans.v[i+j-1]+=a.v[i]*b.v[j]; //先按乘法原理乘一遍,就跟普通的一样
}
}
ans.l=a.l+b.l; //最多吗
for(int i=1;i<=ans.l;i++)
{
if(ans.v[i]>=rad) //开始按3位处理了
{
if(i == ans.l) ans.l++;
ans.v[i+1]+=ans.v[i]/rad;
ans.v[i]%=rad;
}
}
while(ans.l>0 && ans.v[ans.l] == 0) ans.l--; 如果前导是0删掉。
return ans;
}
data operator+(data a,int p)
{
a.v[1]+=p;
int id=1;
while(a.v[id]>=rad)
{
a.l=max(id+1,a.l);
a.v[id+1]+=a.v[id]/rad;
a.v[id]%=rad;
id++;
a.l=max(id,a.l);
}
return a;
}
data operator-(data a,data b)
{
for(int i=1;i<=a.l;i++)
{
a.v[i]-=b.v[i];
if(a.v[i]<0)
{
a.v[i]+=rad;
a.v[i+1]--;
}
}
while(a.l>0 && a.v[a.l]==0) a.l--;
return a;
}
data operator^(data a,int p)
{
data ans;
ans.l=1;
ans.v[1]=1;
for(int i=p;i>=1;i--)
{
ans=ans*a;
}
return ans;
}
void print(data a)
{
printf("%d",a.v[a.l]);
for(int i=a.l-1;i>=1;i--)
{
printf("%03d",a.v[i]);
}
printf("\n");
}
int main()
{
scanf("%d%d",&n,&d);
if(d == 0)
{
puts("1");
return 0;
}
dp[0].l=1;
dp[0].v[1]=1;
for(int i=1;i<=d;i++)
{
dp[i]=(dp[i-1]^n)+1;
}
print(dp[d]-dp[d-1]);
return 0;
}