[51Nod 1048] 整數分解為2的冪 V2
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
(1 <= N <= 10^30)
Solution
O(N)的做法十分顯然。
既然N這麼大了,考慮log 做法
假定
似乎它與
設
這樣很好的避免了重複問題。
顯然
事實上,
那麼只需要儲存
DP就變為2維的了。
複雜度
N不是
完全可以將N二進位制分解,在有1的位置做DP,方法同上面相同,因為兩個二進位制位間相互獨立,互不影響。相當於將前面所有二進位制位合併後,與當前位合併,一直合併下去。
複雜度同樣
高精度注意常數優化。
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#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 N 105
#define cl(a) memset(a,0,sizeof(a));
#define lq 1000000000
using namespace std;
typedef long long LL;
int m,p[N];
LL cf[11];
struct node
{
int a[180];
}f[N][N],g[N][N],n;
node operator *(node x,node y)
{
node z;
cl(z.a);
z.a[0]=x.a[0]+y.a[0]-1;
if((!x.a[1]&&x.a[0]<2)||(!y.a[1]&&y.a[0]<2))
{
z.a[0]=1,z.a[1]=0;
return z;
}
fo(i,1,x.a[0])
{
fo(j,1,y.a[0])
{
LL v=(LL)x.a[i]*(LL)y.a[j]+(LL)z.a[i+j-1];
z.a[i+j]+=(int)(v/lq);
z.a[i+j-1]=(int)(v%lq);
}
}
if(z.a[z.a[0]+1]) z.a[0]++;
return z;
}
node operator +(node x,node y)
{
node z;
cl(z.a);
z.a[0]=max(x.a[0],y.a[0]);
fo(i,1,z.a[0])
{
z.a[i+1]+=(z.a[i]+=x.a[i]+y.a[i])/lq;
z.a[i]%=lq;
}
z.a[0]+=(z.a[z.a[0]+1]);
return z;
}
node operator /(node x,LL y)
{
node z;
memset(z.a,0,sizeof(z.a));
z.a[0]=x.a[0];
fod(i,z.a[0],1)
{
if(i!=1) z.a[i-1]+=(z.a[i]+x.a[i])%y*lq;
z.a[i]=(z.a[i]+x.a[i])/y;
}
z.a[0]-=(!z.a[z.a[0]]);
return z;
}
int get()
{
node n1=n;
int i=0;
while(n1.a[0])
{
if(n1.a[1]%2) p[++p[0]]=i;
n1=n1/2,i++;
}
return i;
}
int main()
{
char st[2000];
scanf("%s",st+1);
cf[0]=1;
fo(i,1,10) cf[i]=cf[i-1]*10;
int l1=strlen(st+1);
fo(i,1,l1) n.a[(i-1)/9+1]+=(st[l1-i+1]-'0')*cf[i-(i-1)/9*9-1];
n.a[0]=(l1-1)/9+1;
int l=get();
f[0][0].a[0]=f[0][0].a[1]=1;
int v=0;
fo(i,1,l)
{
f[i][i].a[0]=f[i][i].a[1]=1;
fo(j,0,i-1)
{
f[i][j].a[0]=1;
f[i][j].a[1]=0;
fo(k,0,j) f[i][j]=f[i][j]+f[i-1][k]*f[i-1-k][j-k];
}
}
fo(i,0,p[1]) g[1][i]=f[p[1]][i];
fo(i,2,p[0])
{
fo(j,0,p[i])
{
fo(k,0,j) g[i][j]=g[i][j]+g[i-1][k]*f[p[i]-k][j-k];
}
}
node ans;
cl(ans.a);
fo(i,0,p[p[0]]) ans=ans+g[p[0]][i];
fod(i,ans.a[0],1)
{
if(i!=ans.a[0]) fod(j,8,1) if(ans.a[i]<cf[j]) printf("0");
printf("%d",ans.a[i]);
}
}
相關推薦
[51Nod 1048] 整數分解為2的冪 V2
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
51Nod 1383&1048 整數分解為2的冪
題目 任何正整數都能分解成2的冪,給定整數N,求N的此類劃分方法的數量。 V1:n≤106n≤106。要對答案模1e9+71e9+7。 V2:n≤1030n≤1030。將整個答案輸出。 解題
51nod 1383 整數分解為2的冪(數列,也可以自己根據觀察找規律推理得到遞推公式)
描述: 組合數學生成函式 1383 整數分解為2的冪 1 秒 131,072 KB 80 分 5 級題 任何正整數都能分解成2的冪,給定整數N,求N的此類劃分方法的數量!由於方案數量較大,輸出
51Nod-1383-整數分解為2的冪
ACM模版 描述 題解 看到這裡,我們應該可以想到,這是一個數論問題,應該是一個什麼數列,暴力解出來小資料後,在 OEIS 中查看了一下下,發現的確是一個十分有趣的數列——Binary partition function: number of p
[51nod1383&1048]整數分解為2的冪
題目大意 任何正整數都能分解成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
51nod 1383 整數分解為2的冪(遞推)
Description 任何正整數都能分解成2的冪,給定整數N,求N的此類劃分方法的數量!由於方案數量較大,輸出Mod 1000000007的結果。 比如N = 7時,共有6種劃分方法。 7=1+1+1+1+1+1+1 =1+1+1+1+1+2
51nod 1383 整數分解為2的冪
#include<bits/stdc++.h> using namespace std; const int MAXN=1000100; const int mod=1e9+7; int
[51Nod 1383] 整數分解為2的冪
Description 任何正整數都能分解成2的冪,給定整數N,求N的此類劃分方法的數量!由於方案數量較大,輸出Mod 1000000007的結果。 比如N = 7時,共有6種劃分方法。
51nod-1383 整數分解為2的冪
原題連結 收藏 關注 任何正整數都能分解成2的冪,給定整數N,求N的此類劃分方法的數量!由於方案數量較大,輸出Mod 1000000007的結果。 比如N = 7時,共有6
【51NOD 1383】整數分解為2的冪
DH ---------以上初三THU/PKU大爺---- Alan_cty LYD XHM HZJ ZZ ---以下是大神%-- YMW Samjia2000 werkeytom_ftd Crazy_czy WorldWide_D Yxuan
[51nod1138]正整數分解為幾個連續自然數之和
sqrt esp 連續 奇數 mes 判斷 -i 兩個 註意 解題關鍵:註意為什麽上界是$\sqrt {2n} $ 因為函數是關於m的遞減函數,而結果必須為正整數 $a = \frac{{2n + m - {m^2}}}{{2m}} = \frac{n}{m} + \f
PTA7-37 整數分解為若干項之和(20 分)超級詳解
將一個正整數N分解成幾個正整數相加,可以有多種分解方法,例如7=6+1,7=5+2,7=5+1+1,…。程式設計求出正整數N的所有整數分解式子。輸入格式:每個輸入包含一個測試用例,即正整數N (0<N≤30)。輸出格式:按遞增順序輸出N的所有整數分解式子。遞增順序是指:
一個正整數分解為幾個連續的正整數之和
題目: 給定你一個數字 如:15 15可分解為 7+8 4+5+6 1+2+3+4+5 再如: 8 8不可分解為任何連續的正整數之和 所以輸出NONE 此題就是給定一個數字如果這個數字可以分解為
7-37 整數分解為若干項之和(20 分)
題目連結(組合版):點選開啟連結題目大意:略。解題思路:此方法僅限於輸出組合情況,計數的話會TLE。附加題目(計數版):點選開啟連結AC 程式碼(組合版)#include<bits/stdc++.
PTA 7-12 整數分解為若干項之和(20 分)
將一個正整數N分解成幾個正整數相加,可以有多種分解方法,例如7=6+1,7=5+2,7=5+1+1,…。程式設計求出正整數N的所有整數分解式子。 輸入格式: 每個輸入包含一個測試用例,即正整數N (0 < N ≤ 30)。 輸出格式: 按遞增順序輸出N的所有整數分解式
正整數分解為n個連續正整數
思路:等差數列求和: sn=a1*n+n*(n-1)*d/2 在這裡d為1 #include<stdio.h> //#define N 1000 #define M 10 void print(int k) {int sn=0,t=0;for(int a1=1;
7-1 整數分解為若干項之和(20 分)(dfs)
思路:不帶標記的dfs,只要沒有超過和就不斷dfs直到超過了之後向前回溯。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math
(PTA)7-1 整數分解為若干項之和
題目 將一個正整數N分解成幾個正整數相加,可以有多種分解方法,例如7=6+1,7=5+2,7=5+1+1,…。程式設計求出正整數N的所有整數分解式子。 輸入格式: 每個輸入包含一個測試用例,即正整數N (0 輸出格式: 按遞增順
pta 5-37 整數分解為若干項之和 (遞迴)
5-37 整數分解為若干項之和 (20分) 將一個正整數N分解成幾個正整數相加,可以有多種分解方法,例如7=6+1,7=5+2,7=5+1+1,…。程式設計求出正整數N的所有整數分解式子。 輸入格式: 每個輸入包含一個測試用例,即正整數N (0<<
面試總結:任意一個整數分解為幾個連續正整數之和
前陣子參加了國內某一大公司的面試。到了之後,人家不問出身,不問來歷,就直接開機讓我上機程式設計。因為是第一次在面試時上機操作,儘管題目不是很難,但是由於沒搞清楚機考和筆試的區別,導致最後面試失敗。現在總結一下自己在機考時碰到的一些問題,以免自己以後再犯同樣的錯