UVA - 12716

这是一道要转两次弯的数论题

题意 a^b=c=gcd(a,b),求在N以内有多少对这样的数

一开始我觉得可以枚举a c 求b,但是这样范围太大,担心会T,后来看了别人的题解,发现可以把c放在外圈,a放在内圈,这样可以减少a遍历的个数

类似于素数筛,这样每次枚举都会 有一次判断 gcd(a,b)=c?的操作,总共复杂度为n(logn)^2,通过多次枚举,发现一个规律,b=a-c;

所以复杂副减少为n(logn)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<math.h>
#include<map>
#define MST(vis,x) memset(vis,x,sizeof(vis))
#define INF 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define maxn  30000005
using namespace std;
int s1[maxn];
int main()
{
    int t,n,sum,i=1;
    for(int c=1; c<=maxn/2; c++)
    {
        for(int a=c+c; a<=maxn; a+=c)
        {
            int b=a-c;
            if((a^b)==c)
                s1[a]++;
        }
    }
    for(int a=2;a<maxn;a++)
        s1[a]+=s1[a-1];
    cin >> t;
    while(t--)
    {
        scanf("%d",&n);
        sum=0;
        printf("Case %d: %d\n",i++,s1[n]);
    }
    return 0;
}
View Code

 

posted @ 2017-08-14 15:02  被咬过的馒头  阅读(126)  评论(0编辑  收藏  举报