题目链接:传送门
显然是 dp。
令
d
p
[
i
]
dp[i]
dp[i]表示分解
i
i
i的方案数。
考虑怎样推出
d
p
[
i
]
dp[i]
dp[i]:
若
i
i
i为奇数,则
i
i
i的分解式中必然有一个1。
若减去这个1,则变为
i
−
1
i-1
i−1的分解式。
任意
i
−
1
i-1
i−1的分解式后+1,则变为
i
i
i的分解式。
因此
i
i
i的分解方案与
i
−
1
i-1
i−1的分解方案是一一对应的。
所以
d
p
[
i
]
=
d
p
[
i
−
1
]
dp[i]=dp[i-1]
dp[i]=dp[i−1]。
若
i
i
i为偶数,则有两种情况:分解方案中有1和没有1。
如果有1,则1的数量至少有2个。
减去这两个1,发现变为了
i
−
2
i-2
i−2的分解。
若没有1,则分解式中的所有数均为2的倍数。
所以把所有数都除以2,变为了
i
2
\frac{i}{2}
2i的分解。
因此
d
p
[
i
]
=
d
p
[
i
−
2
]
+
d
p
[
i
/
2
]
dp[i]=dp[i-2]+dp[i/2]
dp[i]=dp[i−2]+dp[i/2]。
代码:
#include<stdio.h>
#include<cstring>
#include<algorithm>
#define re register int
using namespace std;
typedef long long ll;
int read() {
re x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9') {
x=10*x+ch-'0';
ch=getchar();
}
return x*f;
}
ll fastpow(ll b,ll p,ll k) {
ll ans=1;
while(p) {
if(p&1) ans=ans*b%k;
b=b*b%k;
p>>=1;
}
return ans;
}
const int Size=1000005;
const ll mod=1e9;
ll n,dp[Size];
int main() {
n=read();
dp[0]=dp[1]=1;
for(re i=2; i<=n; i++) {
if(i&1) {
dp[i]=dp[i-1];
} else {
dp[i]=(dp[i-2]+dp[i>>1])%mod;
}
}
printf("%lld",dp[n]);
return 0;
}