我这里在原题目上面加了扩充
修改:将2018改为x(x不是很大 ,其他题面内容不变
方法:首先将x分解质因子,变为 x = p 1 e 1 ∗ p 2 e 2 ∗ . . . ∗ p n e n x=p_{1}^{e1}*p_{2}^{e2}*...*p_{n}^{en} x=p1e1∗p2e2∗...∗pnen的形式
在[a,b]区间我们枚举 %x的余数 i ∈ [ 0 , x − 1 ] i\in [0,x-1] i∈[0,x−1] ,.然后将 i 里x的质因子的数除掉,不够的乘起来,最后得到一个数y,相当于找到最小的y满足 i ∗ y % x = 0 i*y\%x = 0 i∗y%x=0,则i对应的是[c,d]里y倍数的数量
单次询问时间复杂度: O ( x ∗ x p r i 数 量 ) O(x*x_{pri数量}) O(x∗xpri数量)
将下面代码修改下可以过掉那题(文章最后面)。
代码如下
#include
#define LL long long
const int N = 2e5+5;
using namespace std;
int x,a,b,c,d;
LL s1(int l,int r,int mo){
//得到[l,r]里%x==mo的数量
if(mo==0)mo=x;
int ans=r/x - (l-1)/x;
if(r%x>=mo)ans++;
if((l-1)%x>=mo)ans--;
return ans;
}
LL s2(int l,int r,int mo){
//得到[l,r]为mo倍数的数量
return r/mo-(l-1)/mo;
}
int pr[100][2],len;
int main(){
cin>>x>>a>>b>>c>>d;
int lx=x;
for(int i=2;i*i<=lx;i++)
if(lx%i==0){
pr[++len][0]=i;
while(lx%i==0)
pr[len][1]++,lx/=i;
}
if(lx!=1)pr[++len][0]=lx,pr[len][1]=1;
LL ans=s1(a,b,0)*(d-c+1);//特判i=0
for(int i=1;i<x;i++){
int y=1,li=i;
for(int j=1;j<=len;j++){
int js=0;
while(li%pr[j][0]==0)
li/=pr[j][0],js++;
if(js>=pr[j][1])js=0;
else js=pr[j][1]-js;
while(js--)
y*=pr[j][0];
}
ans+=s1(a,b,i)*s2(c,d,y);
}
printf("%lld\n",ans);
return 0;
}
/**
2018 1 2 1 2018
2018 1 2018 1 2018
2018 1 1000000000 1 1000000000
*/
能AC这题的代码
#include
#define LL long long
const int N = 2e5+5;
using namespace std;
int x,a,b,c,d;
LL s1(int l,int r,int mo){
//得到[l,r]里%x==mo的数量
if(mo==0)mo=x;
int ans=r/x - (l-1)/x;
if(r%x>=mo)ans++;
if((l-1)%x>=mo)ans--;
return ans;
}
LL s2(int l,int r,int mo){
//得到[l,r]为mo倍数的数量
return r/mo-(l-1)/mo;
}
int pr[100][2],len;
int main(){
x=2018;
int lx=x;
for(int i=2;i*i<=lx;i++)
if(lx%i==0){
pr[++len][0]=i;
while(lx%i==0)
pr[len][1]++,lx/=i;
}
if(lx!=1)pr[++len][0]=lx,pr[len][1]=1;
while(cin>>a>>b>>c>>d){
LL ans=s1(a,b,0)*(d-c+1);//特判i=0
for(int i=1;i<x;i++){
int y=1,li=i;
for(int j=1;j<=len;j++){
int js=0;
while(li%pr[j][0]==0)
li/=pr[j][0],js++;
if(js>=pr[j][1])js=0;
else js=pr[j][1]-js;
while(js--)
y*=pr[j][0];
}
// printf("y=%d\n",y);
//printf("i=%d %d %d\n",i,y,s1(a,b,i)*s2(c,d,y));
ans+=s1(a,b,i)*s2(c,d,y);
}
printf("%lld\n",ans);
}
return 0;
}
/**
*/