【[SCOI2006]整数划分】

高精,拆分

要求整数划分,且积越大,就如同矩形周长划分求面积最大,那么就是正方形最大,即越平均答案越大。
于是,将一个数划分,就是不断分成两份的过程,如果是奇数则为n/2和n/2+1,偶数则为n/2和n/2,最终结果必定是x个3和y个2。
由于2^3=8,2+2+2=6,而3^2=9,3+3=6,如果遇到3个2则用两个3替换

代码

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
long long n;
queue<long long>q;
int f[50005],cnt=1;//储存原数
int a[50005];//进位数组
int c2,c3;
void change(int x)
{
    for(int i=1;i<cnt;++i)
    {
        f[i]*=x;
        if(f[i]>=10)
        {
            a[i+1]=f[i]/10;
            f[i]=f[i]%10;
        }
    }//第一次乘和进位处理,一定要开一个数组不然会把进位的数一起做下一次乘法
    f[cnt]*=x;
    if(f[cnt]>=10)
    {

        a[cnt+1]=f[cnt]/10;
        f[cnt]=f[cnt]%10;
        cnt++;
    }//当超出当前最大位数时要加特判进位,并更新最大位数cnt
    for(int i=1;i<=cnt;++i)
    {
        f[i]=a[i]+f[i];
        if(f[i]>=10)
        {
            f[i+1]+=f[i]/10;
            f[i]=f[i]%10;
            if(i==cnt) cnt++;
        }   
    } //加上进位的数,并且也要判断是否需要进位
    memset(a,0,sizeof(a));//用完清零
}
int main()
{
    scanf("%d",&n);
    q.push(n);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        if(x==2||x==3)
        {
            (x==2)?c2++:c3++;
            continue;
        }
        q.push(x/2);
        q.push(x-x/2);
    }//队列分解因数
    if(c2>=3)
    {
        c3+=c2/3*2;
        c2=c2%3;
    }//用3替换2
    f[1]=1;//初值不能为0
    for(int i=1;i<=c3/2;++i)
    change(9); //由于我的算法为一位乘多位,3也是乘,9也是乘,不如用9替换3可以节约一点时间
    if(c3%2!=0)
        change(3);//多出的3要乘回
    if(c2!=0)//这里一定要特判,在下因为没特判碰见3的倍数就全部输出0
    change(c2*2);
    cout<<cnt<<endl;
    reverse(f+1,f+cnt+1);//数组翻转,其实无所谓,只不过看起来舒服
    for(int i=1;i<=min(100,cnt);i++)
        cout<<f[i];
}

其实这题直接拿一个模板做也非常简单,只不过既然都拆分开了不如直接做,而且一位乘多位代码实现也比多位乘多位简单易懂的多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值