bzoj 1089

很久没有写博客了呢。

今天来补一补。

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;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值