首页 > 代码库 > 51Nod1333--无聊的数学家们

51Nod1333--无聊的数学家们

题意 : (蛮有意思的一个小故事) 有三个数学家,A,B与C。A选了两个正整数x与y满足x<=y。然后,A将x+y的值告诉了B,A又将x*y的值告诉了C。B与C都不知道x与y分别是什么,也不知道对方得到的值是什么。但B和C知道A告诉B的值是某两个正整数的“和”而告诉C的值是这两个数的“积”。而且这三个数学家的数学功底足够好。下面是B与C进行的对话:
B:“我确定你一定没有百分百的把握猜中我得到的数。”
C:“谢谢你的提示。现在我能确定你获得的数是 S。”
故事结束,回到问题。
这个故事中一共涉及3个未知参数x,y与S,其实由于S=x+y,所以实际一共只有两个未知参数而已。你可以带入一些正整数让这个故事没有逻辑漏洞。现在问题来了,在区间[L,R]上存在多少个数值t,使S=t时能找到对应的x与y,并让这个故事成立。输出这些t的和(1<=L<=R<=5,000,000)。

------------------------------------------------------------此后一千里------------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

稍微想了一下,发现有几个关键点。

一是如果C能百分百确定x和y,那么x*y一定是个质数,即xy中一个为1,一个为质数

然后反推出x+y-1不是个质数,因为B肯定C不能百分百确定

二是C根据B的言语知道x+y-1不是个质数就能推出自己的数,那说明所有x*y=a*b里面,只有一组ab不满足a+b-1是质数

然后发现x*y总能拆成1*x*y,而根据上面的推理,x*y不是个质数,所以唯一拆分即为x*y,1,所以其他拆分如果不满足a+b-1是个质数,那么这个S就不可行

然后每个S可行与否可以去筛出来

代码 :

技术分享
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define low(x) ((x)&(-(x)))
#define LL long long
#define eps 1e-9
using namespace std;

#define int int
inline int Max(int a,int b) {return a>b?a:b;}
inline int Min(int a,int b) {return a<b?a:b;}
inline int Abs(int a) {return a>0?a:-a;}
inline int Sqr(int a) {return a*a;}
#undef int

#define MAXN 5000005

LL pre[MAXN];bool ok[MAXN];
bool mk[MAXN];int pri[MAXN],cnt,n;

void Pre(int n) {
    for(int i=2;i<=n;i++) {
        ok[i]=1;
        if(!mk[i]) pri[++cnt]=i;
        for(int j=1;j<=cnt&&i*pri[j]<=n;j++) {
            mk[i*pri[j]]=1;
            if(i%pri[j]==0) break;
        }
    }
    for(int i=2;i<=n;i++) 
        for(int j=i+i;j<=n;j+=i) 
            ok[j]&=!mk[i+j/i-1];
    for(int i=2;i<=n;i++) 
        pre[i]=pre[i-1]+(ok[i-1]&&mk[i-1]?i:0);
}

int main() {
    int T,l,r;cin>>T;
    Pre(5000000);
    while(T--) {
        scanf("%d%d",&l,&r);
        printf("%lld\n",pre[r]-pre[l-1]);
    }
    return 0;
}
View Code

 

51Nod1333--无聊的数学家们