51nod 1383&1048 整数分解为2的幂 [递推]【数学】
来源:互联网 发布:手机电影同声传译软件 编辑:程序博客网 时间:2024/06/10 17:51
题目连接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1048
————————————————————————————————————-.
整数分解为2的幂
基准时间限制:3 秒 空间限制:131072 KB 分值: 1280 难度:9级算法题
任何正整数都能分解成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
Input
输入N(1 <= N <= 10^30)
Output
划分方法的数量
Input示例
7
Output示例
6
————————————————————————————————————-.
首先能够dp
设dp[i][j]表示组成的数是
为了避免重复,dp[i][j]转移时枚举下一个数必须大于等于
那么可以得出:
能够做到
通过打表找规律等 ,可以递推得到如下规律
这样的话复杂度就是
然而对于51nod 1383 这个复杂度就够用了,但是对于1048的
如果n很大怎么办?
那样就要挖掘一下分解方案的性质了。
1.对于一个数n,假设它二进制下有m个1,分别是第
2.对于一个数
证明并不难。有了这些性质,就可以设新的状态了。
首先设g[i][j]表示做完了前i段(即n二进制下的前i个1位),最大的数是
再设一个辅助数组f[i][j],表示组成
接下来枚举第
其中
f[i][j]的转移类似
时间复杂度
转(chao)自(xi)
附本题代码
———————————————————————————-.
int dp[N];int main(){ int n; scanf("%d",&n); dp[0]=1; for(int i=1;i<=n;i++){ if(i&1){ dp[i]=dp[i-1]; } else { dp[i]=dp[i-1]+dp[i/2]; } if(dp[i]>MOD) dp[i]-=MOD; } printf("%d\n",dp[n]); return 0;}
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=99,M=170,mo=1e9;typedef long long LL;char c[N];int tot;struct num{ int w,a[M];}f[N+5][N+5],ans,n,p,t,s[N+5],g[N+5][N+5];num operator + (const num &a,const num &b){ t.w=max(a.w,b.w); //t.a[1]=0; memset(t.a,0,sizeof(t.a)); for (int i=1;i<=t.w;i++) { t.a[i]+=a.a[i]+b.a[i]; if (t.a[i]>=mo) { t.a[i+1]=1; t.a[i]-=mo; }//else t.a[i+1]=0; } if (t.a[t.w+1]>0) t.w++; //memset(t.a+t.w+1,0,sizeof(t.a+t.w+1)); return t;}num operator * (const num &a,const num &b){ memset(t.a,0,sizeof(t.a)); for (int i=1;i<=a.w;i++) { for (int j=1;j<=b.w;j++) { t.a[i+j]+=(t.a[i+j-1]+(LL)a.a[i]*b.a[j])/mo; t.a[i+j-1]=(t.a[i+j-1]+(LL)a.a[i]*b.a[j])%mo; } } for (t.w=a.w+b.w;t.w>1 && t.a[t.w]==0;t.w--); return t;}int main(){ freopen("data.out","w",stdout); scanf("%s",c+1); int l=strlen(c+1); n.w=l/9+1; for (int i=1;i<=l;i++) { int j=(l-i)/9; n.a[j+1]=n.a[j+1]*10+c[i]-48; } f[0][0].w=f[0][0].a[1]=1; for (int i=1;i<=N;i++) { for (int j=0;j<i;j++) { for (int k=0;k<=j;k++) { f[i][j]=f[i][j]+f[i-1][k]*f[i-1-k][j-k]; } } f[i][i].w=f[i][i].a[1]=1; } tot=0; for (int i=0;i<=N;i++) { if (n.a[1]&1) { tot++; if (tot==1) { for (int j=0;j<=i;j++) g[1][j]=f[i][j]; }else { for (int j=0;j<=i;j++) { for (int k=0;k<=j;k++) { g[tot][j]=g[tot][j]+g[tot-1][k]*f[i-k][j-k]; } } } } int r=0; for (int j=n.w;j;j--) { int t=n.a[j]; n.a[j]=((LL)r*mo+t)/2; r=((LL)r*mo+t)%2; } } for (int i=0;i<=N;i++) ans=ans+g[tot][i]; printf("%d",ans.a[ans.w]); for (int i=ans.w-1;i;i--) { for (int j=1e8;j;j/=10) { printf("%d",ans.a[i]/j); ans.a[i]%=j; } } printf("\n"); return 0;}
- 51nod 1383&1048 整数分解为2的幂 [递推]【数学】
- 51nod 1383 整数分解为2的幂【递推】
- 51nod 1383 整数分解为2的幂(递推)
- 【51NOD 1048】【51NOD 1383】整数分解为2的幂 V2
- 51nod-1383 整数分解为2的幂
- 【51Nod 1383】整数分解为2的幂
- 51nod 1383 整数分解为2的幂
- 【51NOD 1383】整数分解为2的幂
- [51Nod 1383] 整数分解为2的幂
- 51nod 1383 整数分解为2的幂
- 51Nod-1383-整数分解为2的幂
- [51Nod 1048] 整数分解为2的幂 V2
- [递推] 51Nod1383 整数分解为2的幂
- 51nod 整数分解为2的幂
- [DP]51 Nod——[1048 整数分解为2的幂 V2]
- 1383 整数分解为2的幂
- [51nod1383&1048]整数分解为2的幂
- 整数分解为2的幂
- React Native 动画研究与实践
- 【Java】一次SpringMVC+ Mybatis 配置多数据源经历
- Eclipse的Servers视图中无法添加Tomcat6/Tomcat7
- 提高C#编程水平的50个要点 之十三“使用静态构造函数来初始化静态成员变量”
- yii2默认路径
- 51nod 1383&1048 整数分解为2的幂 [递推]【数学】
- 空间二次曲面数据拟合算法推导及仿真分析
- $.ajax()方法参数详解
- 选择排序
- 昨天突然想远程登陆vnc,控制树莓派,结果忘记密码了!!!
- The C++ Standard Library 学习计划 + 目录
- 出现Could not allocate CursorWindow of size due to error -12.错误的解决方案
- Python 序列函数
- Spring Aspect的Execution表达式