【51NOD 1048】【51NOD 1383】整数分解为2的幂 V2

来源:互联网 发布:部落冲突防御设施数据 编辑:程序博客网 时间:2024/06/17 08:31

Description

任何正整数都能分解成2的幂,给定整数N,求N的此类划分方法的数量!
比如N = 7时,共有6种划分方法。

7=1+1+1+1+1+1+1
=1+1+1+1+1+2
=1+1+1+2+2
=1+2+2+2
=1+1+1+4
=1+2+4

Solution

gi,j,k表示一个序列组成2i这个数,这个序列中最大的数为2j,最小的为2k的方案数;
fi,j表示已经做完了输入的数的后i位二进制,序列中最大的数为2j的方案数;

gi,j,k=l=kjgi1,j,l(t=klgi1,t,k)

fi,j=k=1jgi,j,k(l=1kfi1,l)

有两个很显然可以用前缀和,
复杂度:O(n4)

优化:
发现有性质

gi,j,k=gi1,j1,k1=gi2,j2,k2=......

所以只要记录gi,j表示由最大2j最小20组成2i的方案数即可,

注意题目没有mo,要用高精度!
复杂度:O(n3)

Code

标程只加了gi,j,k=gi1,j1,k1的优化,所以很丑QwQ而且还要卡常QwQ:
这里写图片描述

#include <cstdio>#include <cstdlib>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define max(q,w) ((q)>(w)?(q):(w))using namespace std;typedef long long LL;const int N=102,YW=1000000000,YW1=9;int m,n;int a[N],z[N];struct qqww{    int n;    int a[151];}f[2][N],g[2][N][N],LIN,YI,t;int ss(int w){    if(!a[0])return 0;    int q=0;    fod(i,a[0],1)    {        a[i]+=q*10;        q=a[i]&1;a[i]>>=1;    }    if(!a[a[0]])a[0]--;    int OU=q;    q=ss(w+1)+1;    z[w]=OU;    return q;}qqww s;qqww operator * (qqww a,qqww b){    if((a.n<2&&a.a[1]==0))return a;    if((b.n<2&&b.a[1]==0))return b;    fo(i,1,s.n)s.a[i]=0;    s.n=a.n+b.n-1;    fo(i,1,a.n)        fo(j,1,b.n)        {            LL t=s.a[i+j-1]+(LL)a.a[i]*b.a[j];            s.a[i+j-1]=t%YW;            s.a[i+j]+=t/YW;        }    while(s.a[s.n+1])    {        s.n++;        s.a[s.n+1]+=s.a[s.n]/YW;        s.a[s.n]%=YW;    }    return s;}qqww operator + (qqww a,qqww b){    a.n=max(a.n,b.n);    fo(i,1,a.n)    {        a.a[i]+=b.a[i];        while(a.a[i]>=YW)        {            a.a[i+1]++;            a.a[i]-=YW;        }    }    while(a.a[a.n+1])    {        a.n++;        a.a[a.n+1]+=a.a[a.n]/YW;        a.a[a.n]%=YW;    }    return a;}int main(){    char ch;    for(char ch=getchar();ch<='9'&&ch>='0';ch=getchar())a[++a[0]]=ch-48;    fo(i,1,a[0]/2)    {        int t=a[i];        a[i]=a[a[0]-i+1];        a[a[0]-i+1]=t;    }    n=ss(1);    g[0][1][1].n=g[0][1][1].a[1]=1;    fo(i,1,n)f[0][i].n=f[0][i].a[1]=1;    bool nw=1,nwg=1;    fo(i,2,n)    {        fo(I,1,g[nwg][i][i].n)g[nwg][i][i].a[I]=0;        g[nwg][i][i].n=g[nwg][i][i].a[1]=1;        fo(I,1,g[nwg][1][1].n)g[nwg][1][1].a[I]=0;        g[nwg][1][1].n=g[nwg][1][1].a[1]=1;        fo(j,2,i-1)fo(k,2,j)        {            fo(I,1,max(g[nwg][j][k].n,g[!nwg][j-1][k-1].n))g[nwg][j][k].a[I]=g[!nwg][j-1][k-1].a[I];            g[nwg][j][k].n=g[!nwg][j-1][k-1].n;        }        fo(j,1,i-1)        {            fo(I,1,max(t.n,g[!nwg][1][1].n))t.a[I]=g[!nwg][1][1].a[I];            t.n=g[!nwg][1][1].n;            g[nwg][j][1]=(g[!nwg][j][1]*t);            fo(k,2,j)            {                t=t+g[!nwg][k][1];                g[nwg][j][1]=g[nwg][j][1]+g[!nwg][j][k]*t;            }        }        if(z[i])        {            fo(j,1,n)            {                fo(I,1,max(f[nw][j].n,f[nw][j-1].n))f[nw][j].a[I]=f[nw][j-1].a[I];                f[nw][j].n=f[nw][j-1].n;                fo(k,1,n)                    f[nw][j]=f[nw][j]+g[nwg][j][k]*f[!nw][k];            }            nw=!nw;        }        nwg=!nwg;    }    printf("%d",f[!nw][n].a[f[!nw][n].n]);    fod(i,f[!nw][n].n-1,1)printf("%09d",f[!nw][n].a[i]);    printf("\n");    return 0;}
0 0
原创粉丝点击