码迷,mamicode.com
首页 > 其他好文 > 详细

?????TMD

时间:2015-07-31 23:13:53      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:

?????TMD

TimeLimit: 2000/1000 MS (Java/Others)  MenoryLimit: 32768/32768 K (Java/Others)
64-bit integer IO format:%I64d

 

Problem Description
  LH Boy ,别看他平时TMD(挺萌的),到处卖萌,疯疯癫癫的,然而,他却是一位常年混迹在各大Math论坛上,帮助无数误入迷途的Mather解决了各种难题的大神,然而,最近他遇到了一个很蛋疼的问题。这是一个来自论坛上Mather的难题: 
  设X∈[1~N],存在多少个X使得GCD(X,N)>=M,统计符合要求X的个数。
Input
  第一行输入一个整数 T( T<=100) ,表示有T组测试数据。 
  接下来有T组测试数据,每一组测试数据输入一行。每一行输入两个整数 N和 M (2<=N<=1000000000, 1<=M<=N)。
Output
  对于每一组测试案例,在下一行中输出答案、
SampleInput

3
1 1
10 2
10000 72
SampleOutput
1
6
260
题目大意: 
  第一行输入T,表示有T组数据。然后每一行输入N和M,分别表示所要求数的范围为1~N,比较值为M。
 题目意思很简单,就是求解,在数的范围内X∈[1~N],存在多少个X使得GCD(X,N)>=M,统计X符合要求的个数。
 用膝盖骨想想也知道,如果直接暴力遍历N次,每次操作的复杂度高达10^9,肯定会超时的。常规的方法肯定不行。
 
 ①首先,补充一下关于GCD()的一些基础知识。
  1,如果GCD(a,b)=c,则可以知道GCD(a/c,b/c)=1;(  GCD(a,b)=c  <=>  GCD(a/c,b/c)=1  )
  2,设GCD(a,b)=c,如果想要GCD(a,b*d)=c,用①_1可知,
    只需满足GCD(a/c,(b/c)*d)=1即可(这个限制既为,满足最大公约数的要求).
 
 ②然后,我们所要求的是GCD(X,N)>=M,也就是说我们要求一个GCD(X,N)=Z,的数,
  1,如果M==1,则可以知道在[1,N]中任意数X的GCD(X,N)>=1,所以符合要求的个数为N。
  2,如果M>1,则表示我们需要找一个GCD(X,N)>1的数。这样我们就知道X肯定会是N的除了1以外的约数、
  因为,X只有是N除了1以外的约数,才可能会有GCD(X,N)>1存在。而且,GCD(N,X)=X;(约数嘛,你懂得~)
 
 ③再者,我们需要统计的数符合要求的X的个数呢?
  1,正如②_2可以知道GCD(N,X)=X,能够使得GCD()=X的数不一定只有X本身,说的正确点的应该是GCD(N,X*q)=X,
  只需要计算1~N中有多少个(X*q)即可。但是,q是有受限制的,需要满足上述①_2的要求。
         (比如:GCD(15,5)=5,GCD(15,5*3)=15;)
  2,由①_2可知,要使得GCD(N,X*q)=X,需要满足GCD(N/X,q)=1.也就是统计1~N/X中有多少个数与N/X互质。
   是不是觉得有点熟悉了的?=>求1~N中,有多少个与N互质的数,不就是欧拉函数嘛,SUM+=Eular(N/X);
 ④最后,如何不重复的统计其公约数为符合条件X的数呢?
  其实,你每次用欧拉函数统计出来的那些数,都是唯一的,如上面③_2所说的,q是有受限制的,因为这个限制,使得所求出的个数都为不重复的、所以,只需要统计N的符合要求的约数Xi,SUM+=Eular(N/Xi),既为答案、
技术分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 int Eular(int N)
 6 {
 7     int sign=1,i;
 8     for(i=2;i*i<=N;i++)
 9     {
10         if(N%i==0)
11         {
12             N/=i;sign*=i-1;
13             while(N%i==0)
14             {N/=i;sign*=i;}
15         }
16     }
17     if(N>1)
18     sign*=N-1;
19     return sign;
20 }
21 int main()
22 {
23     int A,B,T,i,sign;
24     scanf("%d",&T);
25     while(T--)
26     {
27         scanf("%d%d",&A,&B);
28         for(i=1,sign=0;i*i<=A;i++)/*分解约数*/
29            if(A%i==0)       /*分解约数,同时判断两边*/
30            {           /*如果为平方数则主需要判断一次*/
31                 if(i>=B)
32                     sign+=Eular(A/i);
33                 if((A/i)!=i&&(A/i)>=B)/*判断是否为平方数*/
34                     sign+=Eular(i);
35            }
36         printf("%d\n",sign);/*输出答案*/
37     }
38     return 0;
39 }
View Code

?????TMD

标签:

原文地址:http://www.cnblogs.com/LWF5201314614/p/4693291.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!