ZOJ Goldbach 长沙

来源:互联网 发布:淘宝lurd模特 编辑:程序博客网 时间:2024/05/04 15:36


题意:将一个小于等于80000的数分成最多三个素数a,b,c的加和乘,求种类数。没有加括号的情况


题目链接:http://acm.zju.edu.cn/changsha/showProblem.do?problemId=28


思路:比赛的时候一直TLE,拙计啊~~~~

就是在去重的时候,在原来的代码上减少那层循环就好了,只需要统计总共的方案数目,除三就行了,把那些有两个数和三个数相同的情况下,在补齐成三次就行了,从o(n^2)降到了o(n),,,


拙计的代码 ,早点来就好了,

#include <iostream>#include <stdio.h>#include <math.h>#include <string.h>#include <stdlib.h>#include <algorithm>using namespace std;#define maxn  80010#define mode 1000000007#define LL long longLL ans;LL add[maxn];LL mul[maxn];bool is[100000];LL prm[10000];LL getprm(LL n){    LL i, j, k = 0;    LL s, e = (int)(sqrt(0.0 + n) + 1);    memset(is, 1, sizeof(is));    prm[k++] = 2; is[0] = is[1] = 0;    for (i = 4; i < n; i += 2) is[i] = 0;    for (i = 3; i < e; i += 2) if (is[i]) {    prm[k++] = i;    for (s = i * 2, j = i * i; j < n; j += s)    is[j] = 0;    }    for ( ; i < n; i += 2) if (is[i]) prm[k++] = i;    return k;}void init(){    memset(add,0,sizeof(add));    memset(mul,0,sizeof(mul));    for(LL i = 0;i<ans;i++){        for(LL j = i;j<ans ; j++){            if(prm[i]+prm[j]>=maxn) break;            add[prm[i]+prm[j]]++;        }    }    for(LL i = 0;i<ans;i++){        for(LL j = i;j<ans ; j++){            if(prm[i]*prm[j]>=maxn) break;            mul[prm[i]*prm[j]]++;        }    }}int main(){    ans=getprm(80010);    init();    LL n,sum,temp;    while(~scanf("%lld",&n)){        sum = 0;        if(is[n]) sum++;        sum = (add[n] + mul[n] + sum)%mode;        LL res=0,flag2=0,flag3=0;        for(int i=2;i<n;i++){            if(is[i] && add[n-i]){                res=(res+add[n-i])%mode;                if(i*2<n){                    if(i*2==(n-i)) flag3+=2;                    else                    if(is[(n-i-i)]) flag2++;                }            }        }        res = (res + flag3 + flag2);        sum = (sum+res/3) %mode;        res=0; flag3=0,flag2=0;        LL a,b,ji;        for(int i=2;i<n;i++){            if(is[i] && (n%i==0) && mul[n/i]){                res=(res+mul[n/i])%mode;                if(i*i<n){ ji=n/i;                    if(ji%i==0){                        a=ji/i;                        if(is[a]){                            if(a==i) flag3+=2;                            else flag2++;                        }                    }                }            }        }        res = (res + flag3 + flag2);        sum = (sum+res/3) %mode;        res=0;        for(int i=2;i<n;i++)        if(is[i] && mul[n-i])            res=(res+1)%mode;        sum = (sum+res) %mode;        printf("%lld\n",sum);    }    return 0;}



原创粉丝点击