【莫比乌斯反演】关于Mobius反演与gcd的一些关系与问题简化(bzoj 2301 Problem b&&bzoj 2820 YY的GCD&&BZOJ 3529 数表)
2015-07-02 14:44
429 查看
首先我们来看一道题
BZOJ 2301 Problem b
2 5 1 5 1
1 5 1 5 2
3
乍一看,大家的force想法:枚举x,y!之后辗转相除!!
但是复杂度已经爆炸。几乎是一个O(n^3)规模的算法
View Code
代码凑合着看吧。。
BZOJ 2301 Problem b
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、kOutput
共n行,每行一个整数表示满足要求的数对(x,y)的个数Sample Input
22 5 1 5 1
1 5 1 5 2
Sample Output
143
HINT
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000。乍一看,大家的force想法:枚举x,y!之后辗转相除!!
但是复杂度已经爆炸。几乎是一个O(n^3)规模的算法
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define maxq 40001 #define maxn 100001 using namespace std; struct ed{ int a,n,m,id,ans; }a[maxq]; bool is_prime[maxn]; int prime[maxn],b=0,mu[maxn],bit[maxn],ans[maxn]; struct sb{ int num,Id; }f[maxn]; void mu_choice() { mu[1]=1; for(int i=2;i<=maxn-1;i++) { if(!is_prime[i])prime[++b]=i,mu[i]=-1; int j=1,t=2*i; while(j<=b&&t<=maxn-1) { is_prime[t]=1; if(i%prime[j]==0) { mu[t]=0; break; } mu[t]=-mu[i]; t=prime[++j]*i; } } for(int i=1;i<maxn;i++) { for(int j=1;j*i<maxn;j++) f[j*i].num+=i; f[i].Id=i; } } bool cmp(const ed A,const ed B) { return A.a<B.a; } bool cmp2(const sb A,const sb B) { return A.num<B.num; } void add(int pos,int num) { while(pos<=maxn-1) { bit[pos]+=num; pos+=pos&-pos; } } int sum(int pos) { int ne=0; while(pos>0) { ne+=bit[pos]; pos-=pos&-pos; } return ne; } void solve(int x) { int last; for(int i=1;i<=a[x].n;i=last+1) { last=min(a[x].n/(a[x].n/i),a[x].m/(a[x].m/i)); ans[a[x].id]+=(sum(last)-sum(i-1))*(a[x].n/i)*(a[x].m/i); } } int main() { #ifndef ONLINE_JUDGE freopen("3529.in","r",stdin); freopen("3529.out","w",stdout); #endif int T,aa,n,m; scanf("%d",&T); for(int i=1;i<=T;i++) { scanf("%d%d%d",&n,&m,&aa); if(n>m)swap(n,m); a[i].a=aa,a[i].n=n,a[i].m=m,a[i].id=i; } mu_choice(); sort(1+a,a+1+T,cmp); sort(1+f,f+maxn,cmp2); int puck=1; for(int i=1;i<=T;i++) { while(puck<maxn&&f[puck].num<=a[i].a) { for(int j=1;j<=((maxn-1)/f[puck].Id);j++) add(j*f[puck].Id,mu[j]*f[puck].num); puck++; } solve(i); } for(int i=1;i<=T;i++) printf("%d\n",ans[i]&0x7fffffff); return 0; }
View Code
代码凑合着看吧。。
相关文章推荐
- Linux 分区初始化为物理卷,把物理卷加入卷组
- 测试
- Nagios 监控Nginx和php-fpm
- hdu3535 AreYouBusy
- 基于android平台开发的计算器
- 通过链接打开iOS上的app store 的搜索页面
- 通过链接打开iOS上的app store 的搜索页面
- mybatis+springMVC新感悟
- Hook钩子编程
- 《Java程序设计》第三次作业:网络编程
- 浅析EF涉及的一些C#语言特性
- opengl中的混合(gl_blend)
- linux mount挂载设备(u盘,光盘,iso等 )使用说明
- 使用Bootstrap v3.3.4注意细节box-sizing
- ZOJ3827 ACM-ICPC 2014 亚洲区域赛的比赛现场牡丹江I称号 Information Entropy 水的问题
- sql 随笔 2015-07-02
- 栈的应用--栈用作判断平衡符号,[()]对的,[(])错的
- background-size 导致的背景不居中问题
- node.js学习笔记之常用模块介绍
- WinCE下串口蓝牙模块的调试