博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 2301: [HAOI2011] Problem b
阅读量:6950 次
发布时间:2019-06-27

本文共 2324 字,大约阅读时间需要 7 分钟。

Time Limit: 50 Sec  Memory Limit: 256 MB
Submit: 2833  Solved: 1256
[][][]

Description

对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

Input

第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k

Output

共n行,每行一个整数表示满足要求的数对(x,y)的个数

Sample Input

2
2 5 1 5 1
1 5 1 5 2

Sample Output

14
3

HINT

100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

题解:

  ,(题解中的容斥定理把c和b写反了,无视就好)

  总结一下,莫比乌斯反演有两种形式

  形式一:

            

  形式二:

          

  本题用到的是第二种形式,题目要求求x∈[a,b],y∈[c,d]。x和y满足gcd(x,y)==k的x和y的数对数。

  令f(i)为x∈[1,N],y∈[1,M],gcd(x,y)==i 的(x,y)数对数。

  令F(i)为x∈[1,N],y∈[1,M],i|gcd(x,y) 的(x,y)数对数。

  可以感觉,a和c的限制有些不好处理,不妨先忘掉a,c的限制。再看形式二,考虑f(i)与F(i)的关系,f(i)是gcd(x,y)==i,F(i)是gcd(x,y)==t*i(t∈Z),所以F(i)=sigma(f(d))(i|d),所以f(i)与F(i)正好满足形式二的第一个,可以利用莫比乌斯反演用F(i)表示f(i)。而F[i]=[N/i]*[M/i]  ([]表示向下取整)

  再考虑a和c的限制,设g(x,y,k)表示[1,x],[1,y] gcd(x1,y1)==k的对数,这个式子其实等价于g(x/k,y/k,1)。

  再有容斥原理可得:Ans=g(b/k,d/k,1)-g((a-1)/k,d/k,1)-g(c/k,b/k,1)+g((a-1)/k,(c-1)/k,1),对于每个g(,,)我们都可以用f()来求。

  O(n)的复杂度不足以解决此题,还有一个O(sqrt(n))的优化,具体看ppt或题解,讲的很清楚。

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 using namespace std;10 typedef long long LL; 11 const LL maxn=50000; 12 LL mu[maxn],prime[maxn],sum[maxn],tot,N;13 bool not_prime[maxn];14 LL a,b,c,d,k,ANS;15 inline void pre(){16 memset(not_prime,false,sizeof(not_prime));17 mu[1]=1;18 for(LL i=2;i<=maxn;i++){19 if(not_prime[i]==false){20 prime[++tot]=i;21 mu[i]=-1;22 }23 for(LL j=1;j<=tot;j++){24 if(i*prime[j]>maxn) break;25 not_prime[prime[j]*i]=true;26 if(i%prime[j]==0){27 mu[prime[j]*i]=0;28 break;29 }30 else mu[prime[j]*i]=-mu[i];31 }32 }33 }34 inline LL solve(LL N,LL M){35 LL ans=0;36 if(N>M) swap(N,M);37 for(LL i=1,la=0;i<=N;i=la+1){38 la=min(N/(N/i),M/(M/i));39 ans+=(sum[la]-sum[i-1])*(N/i)*(M/i);40 }41 return ans;42 } 43 int main(){44 // freopen("b.in","r",stdin);45 // freopen("b.out","w",stdout);46 pre();47 sum[0]=0;48 for(LL i=1;i<=maxn;i++){49 sum[i]=sum[i-1]+mu[i];50 }51 scanf("%d",&N);52 while(N--){53 scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);54 ANS=solve(b/k,d/k)-solve((a-1)/k,d/k)-solve(b/k,(c-1)/k)+solve((a-1)/k,(c-1)/k);55 printf("%lld\n",ANS);56 }57 return 0;58 }

 

 

 

 

转载于:https://www.cnblogs.com/CXCXCXC/p/5264643.html

你可能感兴趣的文章
Bigtable:一个分布式的结构化数据存储系统
查看>>
今天进行的将zzb从apache迁移到nginx
查看>>
PHP缓存
查看>>
CentOS6.5 webserver---网络配置
查看>>
java学习笔记(3)
查看>>
IOS UIView直接响应点击事件的解决方法
查看>>
斯坦福NLP笔记6 —— Defining Minimum Edit Distance
查看>>
关于编辑区无法调用chekbox的问题
查看>>
VMware基础架构和运营管理
查看>>
爱不意味这“sorry”
查看>>
四、 vSphere 6.7 U1(四):部署VCSA
查看>>
apper安卓×××
查看>>
大型网站技术架构(一)大型网站架构演化
查看>>
Log4j 1使用教程
查看>>
如何将PDF转换成Word
查看>>
svn配置
查看>>
ActiveMQ快速入门
查看>>
plusgantt的项目管理系统实战开发最全课程
查看>>
vlan理论03-vlan映射
查看>>
Linux终端的总结和shell
查看>>