Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
建议管理员加强数据&解题报告完全可以把n加强到1e8,因为空间和时间复杂度都是O(n/2). 解题报告: f[i]表示i分解成若干2的幂次的和的方案数. i= 0 1 2 3 4 5 6 7 ... f[i]= 0 1 2 2 4 4 6 6 ... 规律: 若i为奇数,则f[i]=f[i-1]; 若i为偶数,则f[i]=f[i-1]+f[i/2]. 证明: 若i为奇数,则必有1,因为1=2^0,所以减一后得f[i-1], 并且无其他可能拆分的情况. 若i为偶数,则: 取一个1出来,则f[i]=f[i-1]; 不取1出来,则因为i为偶数,f[i]=f[i/2]. 综上,有: f[0]=0,f[1]=1; 转移方程:f[i]=f[i-1]+((!(i%2))?f[i/2]:0). ------------不怎么华丽的分割线------------ 这样就可以过了,但是如果n<=1e8,就不可以定义1e8的数组. 那么利用i为奇数时f[i]=f[i-1],定义f[N/2]的数组, 并且可得: 若i=1,则特判(或可以设f[0]=1,就不用特判了); 若i>1,则首先由1(0和1共用0)到n/2计算出f, 然后算出f[n/2]即可. 贴代码: #include<iostream> #define N 500009 //n=1e8时:#define N 50000009 #define mod 1000000000 using namespace std; int n,f[N]={1}; int main() { cin>>n; for (int i=1;i<=n/2;i++) f[i]=(f[i-1]%mod+f[i/2]%mod)%mod; cout<<f[n/2]%mod<<endl; return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator