RGCDQ
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 323 Accepted Submission(s): 162
In the next T lines, each line contains L, R which is mentioned above.
All input items are integers.
1<= T <= 1000000
2<=L < R<=1000000
See the sample for more details.
2 2 3 3 5
1 1
解题思路:预处理出1000000以内的F(x)可以发现,F(x)的取值是1,2,3,4,5,6,7。而求GCD时,一定是这几个数的组合。那么CGD的结果无非是1,2,3,4,5,6,7。如果我们知道区间[l,r]内,7的值有多少;6的值有多少;5的值有多少;4的值有多少;3的值有多少;2的值有多少;1的值有多少,那么当7的值的个数大于等于2时,结果一定是7;当7的个数小于2,而6的个数大于等于2时,结果一定是6;……………………。因此只要求出区间[l,r]内,1,2,3,4,5,6,7的个数即可,如何求解!!!我们假设s[i][j]的值表示2到i内,F(x)=j(2<=x<=i)的个数,那么区间[l,r]内,7的个数为s[r][7]-s[l-1][7];6的个数为s[r][6]-s[l-1][6];………………,1的个数为s[r][1]-s[l-1][1]。
代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-4)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define mod 1e9+7
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
#define MAX 1000005
//s[i][j]表示在区间[2,i]内F(x)=j(2<=x<=i)的个数
//f[i]表示F(X)的值
int f[MAX],s[MAX][8];
//
void init()
{
int i,j;
memset(f,0,sizeof(f));
//利用筛选素数的方法求解f[x]
for(i=2;i<MAX;i++)
{
if(f[i]==0)
{
for(j=i;j<MAX;j=j+i)
{
f[j]++;
}
}
}
//利用递推公式s[i][j]=s[i][j]+s[i-1][j]求解s[i][j]
for(i=2;i<MAX;i++)
{
for(j=1;j<8;j++)
{
s[i][j]=s[i][j]+s[i-1][j];
}
s[i][f[i]]++;
}
}
int main()
{
init();
int i,j,k,l,r,t;
int num[8];
scanf("%d",&t);
while(t--)
{
memset(num,0,sizeof(num));
scanf("%d%d",&l,&r);
for(i=1;i<8;i++)
num[i]=s[r][i]-s[l-1][i];
if(num[7]>=2)
{
printf("7\n");
continue;
}
if(num[6]>=2)
{
printf("6\n");
continue;
}
if(num[5]>=2)
{
printf("5\n");
continue;
}
if(num[4]>=2)
{
printf("4\n");
continue;
}
if(num[3]>=2||(num[3]>=1&&num[6]>=1))
{
printf("3\n");
continue;
}
if(num[2]>=2||(num[2]>=1&&num[6]>=1)||(num[2]>=1&&num[4]>=1))
{
printf("2\n");
continue;
}
printf("1\n");
}
return 0;
}
预处理过程中的F(X)的求解利用到了类似筛选素数的方法:
筛选法求素数:
原理:在自然数中标记非素数,剩余的数就是素数(注意1特殊处理了)。
操作:从第一个最小的素数开始,即2,标记它的倍数;找下一个离它最近的并且未被标记的数(该数一定是素数),继续标记该数的倍数。按此继续下去即可标记完所有的非素数。
本题求解F(X):
原理:找出X的质因数的个数。
操作:利用筛选法求素数的操作过程,每当一个数被一个素数标记时,意味着X就有一个素因子,则F(X)的值就加1,换句话说,X被标记的次数就是F(X)的值。(注意标记过程中,质因数本身也要标记,这和筛选法有点不同)。
求解F(X)的代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 1000005
int f[MAX];
int main()
{
int i,j,n,x;
memset(f,0,sizeof(f));//初始化
printf("输入区间[2,n]的右端点n(2<n<MAX):\n");
scanf("%d",&n);
for(i=2;i<n;i++)//遍历2到n个数,因为这些数可能是素因子
{
if(f[i]==0)//判断是否是素因子
{
for(j=i;j<n;j=j+i)//寻找以i为素因子的数
{
f[j]++;//
}
}
}
printf("输入f[x]的x:");
while(scanf("%d",&x)!=EOF)
{
printf("f[%d]=%d\n",x,f[x]);
printf("输入f[x]的x:");
}
return 0;
}