題目串連
分析:
題目要求我們給定整數n,要你求在13~n之間的奇數,它可以表示兩個合數相加,對於一個奇數,可能有多種方案,用g(n)表示,問你,要求出sg(n)=sum{g(i)|i<=n};
這和以前的素數表有點類似,先就應該打合數表,然後推出關係,我們可以知道sg(n)=sg(n-2)+g(n),而g(n),n它是一個奇數,我們知道兩個奇數相加一定是偶數,
兩個偶數相加是偶數,所以只有一奇一偶相加才能得到奇數,而偶數一定是合數,那麼,要得到兩個合數,這個奇數一定要為合數,而最小的合數是4且剛好是偶數,前面分析知道另一一定是奇數,所以它就必須每次加2了,相當於n-2*i,這我們就可以發現,只要把n-2*i個數再次分解,看它能否分解兩個合數相加,又已知它又是個奇數,這樣,經
推理,實際上是求前n-2,n-4....13,的個數和,它明顯是個遞迴,方程可以寫為:g(n)=judge(n-4)+g(n-2);這裡n是奇數,judge(i)判斷i是否為合數,是為1,否為0。偶數減一個1就行了。
解決這個問題,這題就不難了。O(n)的時間複雜度絕對完美!
代碼如下:
#include<stdio.h>#include<math.h>typedef long long LL;const long N=1000005;int used[N];LL sg[N];void comp() //合數篩選。{long i,j,idx=-1;for(i=4;i<N;i+=2){used[i]=1;}int m=(int)sqrt(1.0*N);for(i=3;i<m;i+=2){if(used[i]) continue;int k=2*i;for(j=i*i;j<N;j+=k) used[j]=1;}}int main(){LL i,j,n,g=0;sg[11]=0;comp();for(i=13;i<N;i+=2){g+=used[i-4];sg[i]=sg[i-2]+g; } while(scanf("%lld",&n)!=EOF){if(n%2==0) n=n-1;printf("%lld\n",sg[n]);}}