T3

T3 题解

题目:

题目背景

  • 致远星舰队旗舰——“养生壶”号上(别问为啥,外星人的语言习惯)

  • 装着全致远星最先进的密码保护系统

  • 你作为OI星最强的间谍——(代号:映山红)

  • 偷偷来到了这艘战舰上

  • 你经历重重历险终于来到了战舰的总控室

  • 密码系统作为高级货当然不是静态的

  • 它描绘的是这样一个问题:

  • 计算满足:1到n内,gcd(x,y)为素数的数对有多少。

  • 现在帝国的护卫队已经发现了你的踪迹

  • 你能够使用的就是一台性能与公元$2000$年电脑性能几乎无差的掌上解码器

  • 你需要在尽可能短的时间内算出问题的答案

题目描述

  • 求1≤x,y≤n中 , 满足:gcd(x,y)为素数的数对有多少。

输入格式

  • 一行一个数n

输出格式

  • 一行一个数 , 表示满足条件的数对数量

输入输出样例

输入 #1

4

输出 #1

4

输入 #2

12

输出 #2

39

说明/提示

  • 对于10%的数据,保证n≤10

  • 对于50%的数据,保证n≤105

  • 对于100% 的数据 , 保证n≤107

  • 数据随机生成 , 大佬们可以暴力踩标程 (bushi)

翻译一下题意:给定一个正整数n,求1≤x,y≤n中满足gcd(x,y)为素数的数对有多少。

思路:

既然gcd(x,y)是一个质数,那么我们可以认为,如果我们假设gcd(x,y)的值为p,则gcd(x/p,y/p)的值一定为1。既然这样,那么我们就可以先求出1到n中所有的素数,然后再依次求出对于1到n/p[i]的x和y,满足gcd(x,y)=1的素数的个数。

我们在求对于每一对1≤x,y≤n/p[i]的x和y,满足gcd(x,y)=1的数对的对数时,不妨设x≤y(如果不满足则交换x和y的顺序)。

我们考虑对于每一个确定的y,因为x≤y,所以对于每一对1≤x,y≤n/p[i]的x和y,当我们给定一个确定的y值的时候,满足gcd(x,y)=1的数对的对数就等于φ(y)的值。

因而,对于每一对1≤x,y≤n/p[i]的x和y,满足gcd(x,y)=1的数对的对数就等于∑(i=1->n/p[i])φ(i)。

这样我们就可以得出这道题的完整思路:

我们先跑一遍筛素数(这里用线性筛即可),筛出1到n之间的所有质数,以及求出1到n之间每个数i的φ(i)的值,然后再枚举质数,求出对于1到n的每一个质数p[i],它所对应的∑(i=1->n/p[i])φ(i)的值,最后再一次进行累加求和。

完整代码(by 巨佬HWH):

 1 #include<cstdio>
 2 #define ll long long
 3 using namespace std;
 4 
 5 const ll N=1e7+9;
 6 ll pr[N],ph[N];
 7 
 8 int main()
 9 {
10     register ll n,i,j,k=0,p;
11     register long long s=0,t=0;
12     
13     scanf("%lld",&n);
14     
15     ph[1]=1;
16     for(i=2;i<=n;++i)
17     {    
18         if(!ph[i]) pr[++k]=i,ph[i]=i-1;
19         for(j=1;p=i*pr[j],p<=n&&j<=k;++j)
20         {
21             if(i%pr[j]==0)
22             {
23                 ph[p]=ph[i]*pr[j];
24                 break;
25             }
26             else ph[p]=ph[i]*ph[pr[j]];
27         }
28     }
29     
30     for(i=1,j=k;j;--j)
31     {
32         for(p=n/pr[j];i<=p;++i)t+=ph[i];
33         s+=t;
34     }
35     
36     printf("%lld",(s<<1)-k);
37     return 0;
38 }

猜你喜欢

转载自www.cnblogs.com/qianr/p/13402394.html
T3