51nod 1333

版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/81453527

首先要弄清楚一个东西:B所下的结论是在“C不知道B的结论”的条件下给出的,否则题目就是矛盾的。

先考虑C如何在只知道 C = x y 的情况下确定 S = x + y ,显然此时唯一的方法就是枚举所有的 ( x , C x ) ,如果 x + C x 的值都相等,那么即可确定结果。而通过简单的计算:
a + n a = b + n b
a b = n ( a b ) a b
n = a b
可以知道,给定的 C 中,每一组 x + C x 的值必然互不相同,即当且仅当 s ( C ) = 2 C 是一个素数时,C才可以直接确定 S

那么,如果B能够得出结论”C不可能直接确定 S “,则表示所有的 s ( x ( S x ) ) > 2 ,而显然的, S = p r i m e + 1 是不能满足的,其余情况都能满足。

最后,当C得到B的结论后,能够确定结果当且仅当只有唯一的一组 x + C x p r i m e + 1 ,注意到这组数必然为 ( 1 , C ) (因为 C 不能为素数),故我们得到了结论:一个 S 满足条件,当且仅当 S p r i m e + 1 ,同时对 x | S 1 , x ( 1 , S 1 ) ,都有 x + ( S 1 ) x = p r i m e + 1

故我们枚举 [ 3 , n ] 的因数直接计算即可,时间复杂度 O ( n l o g n )

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
//Container--
//
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;const int up=5e6;
int ds[up+10],pn,pr[up+10];bool bd[up+10];ll sm[up+10];
void _init(){
    int i,j,d,k,t;for(pn=0,i=2;i<=up;++i){
        if(!bd[i])pr[pn++]=i;
        for(j=0;j<pn&&(ll)pr[j]*i<=up;++j){
            bd[pr[j]*i]=1;
            if(!(i%pr[j]))break;
        }
    }
    for(i=3;i<=up;ds[i++]=1);
    for(i=2;i<=up;++i)for(j=i+i;j<=up;j+=i){
        if(bd[i+j/i-1])ds[j]=0;
    }
    for(i=3;i<=up;++i)if(!bd[i])ds[i]=0;
    for(i=3;i<=up;++i)sm[i]=ds[i-1]?i:0;
    for(i=3;i<=up;++i)sm[i]+=sm[i-1];
};

void cl(){
    int i,j;scanf("%d %d",&i,&j);printf("%lld\n",sm[j]-sm[i-1]);
};

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    int t;scanf("%d",&t);for(_init();t--;cl());
    return 0;
};

猜你喜欢

转载自blog.csdn.net/u012345506/article/details/81453527