题解桐桐的猜想

Posted kcn999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解桐桐的猜想相关的知识,希望对你有一定的参考价值。

题目描述

       今天,桐桐在复习素数的知识时,发现了有趣的现象,例如4=2+2,5=2+3,6=3+3,7=2+5等等,桐桐列举了很多数,都是这样,所以她大胆地得出了一个结论:任何一个不小于4的数都能表示成两个质数的和。你能找出一些反例,证明桐桐的结论是错误的吗?

 

输入输出格式

输入格式

       两行,第一行为一个整数n(1≤n≤50);接下来有n行,每行包含一个整数m。3m106(3≤m≤106)

 

输出格式

        共n行,每行对应于每一个m,如果m不能表示成两个质数的和,则输出“NO WAY!”;否则输出一种方案。如果有多种可行方案,输出两个质数的差最大的那一种。

 

输入输出样例

输入样例

2

10

11

 

输出样例

10=3+7

NO WAY!

 

题解

        一般人看到这题都是直接用筛法,事实上这个方法也可以。

技术分享图片
#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int m, n[55], maxn;
int p[1000005];
int a[100005], cnt;

int main()
{
    scanf("%d", &m);
    for(register int i = 1; i <= m; ++i)
    {
        scanf("%d", n + i);
        if(n[i] > maxn) maxn = n[i];
    }
    for(register int i = 2; i <= maxn; ++i)
    {
        if(!p[i]) a[++cnt] = i;
        for(register int j = 1; i * a[j] <= maxn; ++j)
        {
            p[i * a[j]] = 1;
            if(!(i % a[j])) break;
        }
    }
    int op;
    for(register int i = 1; i <= m; ++i)
    {
        op = 0;
        for(register int j = 1; a[j] <= n[i] - a[j]; ++j)
        {
            if(!p[n[i] - a[j]])
            {
                printf("%d=%d+%d
", n[i], a[j], n[i] - a[j]);
                op = 1;
                break;
            }
        }
        if(!op) printf("NO WAY!
");
    }
    return 0;
}
参考程序1

        但实际上这题,其实当m为偶数时间复杂度时是强哥德巴赫猜想,当m为奇数时,应该等于奇数加偶数,而偶数质数只有2,所以就能转换成当m为奇数时,判断m-2是否为质数

技术分享图片
#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int m, n[55], maxn;
int p[1000005];
int a[100005], cnt;

int main()
{
    scanf("%d", &m);
    for(register int i = 1; i <= m; ++i)
    {
        scanf("%d", n + i);
        if(n[i] > maxn) maxn = n[i];
    }
    int srmaxn = sqrt(maxn);
    a[++cnt] = 2;
    for(register int i = 4; i <= maxn; i += 2)
    {
        p[i] = 1;
    }
    for(register int i = 3; i <= srmaxn; i += 2)
    {
        if(p[i]) continue;
        a[++cnt] = i;
        for(register int j = i + i; j <= maxn; j += i)
        {
            p[j] = 1;
        }
    }
    for(register int i = 1; i <= m; ++i)
    {
        if(n[i] & 1)
        {
            if(p[n[i] - 2]) printf("NO WAY!
");
            else printf("%d=2+%d
", n[i], n[i] - 2);
        }
        else
        {
            // 哥德巴赫猜想
            for(register int j = 1; ; ++j)
            {
                if(!p[n[i] - a[j]])
                {
                    printf("%d=%d+%d
", n[i], a[j], n[i] - a[j]);
                    break;
                }
            }
        }
    }
    return 0;
}
参考程序2

       到现在之后,其实这个程序还有优化的地方。

       题目中给的n很小,我们可以把筛法缩减,然后后面暴力判断质数即可,这样就可以做到0ms了。所以合理分析时间复杂度还是很重要的。

技术分享图片
#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int m, n[55], maxn;
int p[1000005];
int a[100005], cnt;

int main()
{
    scanf("%d", &m);
    for(register int i = 1; i <= m; ++i)
    {
        scanf("%d", n + i);
        if(n[i] > maxn) maxn = n[i];
    }
    int srmaxn = sqrt(maxn);
    a[++cnt] = 2;
    for(register int i = 4; i <= srmaxn; i += 2)
    {
        p[i] = 1;
    }
    for(register int i = 3; i <= srmaxn; i += 2)
    {
        if(p[i]) continue;
        a[++cnt] = i;
        for(register int j = i + i; j <= srmaxn; j += i)
        {
            p[j] = 1;
        }
    }
    int op;
    for(register int i = 1; i <= m; ++i)
    {
        if(n[i] & 1)
        {
            op = 0;
            for(register int j = 1; a[j] < n[i] - 2 && j <= cnt; ++j)
            {
                if((n[i] - 2) % a[j]) continue;
                printf("NO WAY!
");
                op = 1;
                break;
            }
            if(!op) printf("%d=2+%d
", n[i], n[i] - 2);
        }
        else
        {
            // 哥德巴赫猜想 
            for(register int j = 1; a[j] <= n[i] - a[j]; ++j)
            {
                for(register int k = 1; a[k] < n[i] - a[j] && k <= cnt; ++k)
                { 
                    if((n[i] - a[j]) % a[k]) continue;
                    goto NO_WAY;
                }
                printf("%d=%d+%d
", n[i], a[j], n[i] - a[j]);
                break;
                NO_WAY:;
            }
        }
    }
    return 0;
}
参考程序3

 

 

以上是关于题解桐桐的猜想的主要内容,如果未能解决你的问题,请参考以下文章

题解桐桐的递归函数

桐桐的糖果计划(tarjan求桥+双连通分量)

vijos1325 桐桐的糖果计划

桐桐的数学游戏(N皇后)

题解阶乘因子

题解数字交换游戏