数论 + 容斥 - HDU 1695 GCD
2015-10-09 20:11
399 查看
GCD
Problem's Link
[b]Mean:[/b]给定五个数a,b,c,d,k,从1~a中选一个数x,1~b中选一个数y,使得gcd(x,y)=k.
求满足条件的pair(x,y)数.
[b]analyse:[/b]
由于b,d,k都是1e5数量级的,普通枚举必定超时.
首先可以把b,d都同时除以k,问题就转化成了求1~b/k和1~d/k中的gcd(i,j)=k的对数.
证明如下:
令Ai∈{1,2,3...b},Bi∈{1,2,3...d}.
如果有:GCD(Ai,Bi)=k
则有:GCD(Ai/k,Bi/k)=1
而对于不能够被k整除的数,不可能有GCD(Ai,Bi)=k.
也就是说,除以K所剔除掉的数都是不满足条件的数,对最终答案没有影响.
这样就大大优化了时间复杂度.
然后就是对1e5以内的数进行质因数分解,使用质因数来构造容斥表.
再枚举1~b/k之间的每一个数,利用容斥原理算出1~d/k中有多少个数与之互质即可.
[b]Time complexity: O(N*logN)[/b]
[b]view code[/b]
/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-10-08-21.45
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define max(a,b) (a>b?a:b)
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);
const int NN=100010;
bool v[NN];
int p[NN];
void makePrime()
{
int num=-1,i,j;
for(i=2; i<NN; ++i)
{
if(!v[i]) { p[++num]=i; }
for(j=0; j<=num && i*p[j]<NN; ++j)
{
v[i*p[j]]=true;
if(i%p[j]==0) { break; }
}
}
}
struct node
{
int fac;
bool ti;
node() {}
node(int a,bool b):fac(a),ti(b) {}
};
vector<node> pa[NN];
void pre()
{
int i,j,a,cnt,si;
for(i=1; i<=100000; ++i)
{
a=i;
cnt=0;
for(j=0; j<=9672; ++j)
{
if(!(a%p[j]))
{
pa[i].push_back(node(p[j],false));
si=pa[i].size();
for(int k=0; k<si-1; ++k)
{
pa[i].push_back(node(pa[i][si-1].fac*pa[i][k].fac,!pa[i][k].ti));
}
while(!(a%p[j]))
a/=p[j];
}
if(p[j]>a || a<=0) break;
}
}
}
int main()
{
makePrime();
pre();
ios_base::sync_with_stdio(false);
cin.tie(0);
int t;
scanf("%d",&t);
for(int Cas=1; Cas<=t; ++Cas)
{
int a,b,c,d,k,si;
scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
if(k==0)
{
printf("Case %d: 0\n",Cas);
continue;
}
a=b/k;
b=d/k;
if(a>b) swap(a,b);
LL ans=b;
if(a==0) ans=0;
for(int i=2; i<=a; ++i)
{
si=pa[i].size();
for(int j=0; j<si; ++j)
{
if(!(pa[i][j].ti))
{
ans+=((b-i+1)-b/pa[i][j].fac+(i-1)/pa[i][j].fac);
}
else
{
ans-=((b-i+1)-b/pa[i][j].fac+(i-1)/pa[i][j].fac);
}
}
}
printf("Case %d: %I64d\n", Cas, ans);
}
return 0;
}
/*
*/
相关文章推荐
- (转)mysql水平分表和垂直分表和数据库分区
- SPOJ Query on a tree (树链剖分 + 线段树)
- Android 应用程序的优先级和进程状态
- 吃糖果
- GPS 偏移校正(WGS-84) 至(GCJ-02) java版本号以实现
- [LeetCode] Ugly Number
- (转)mysql水平分表和垂直分表和数据库分区
- 我的Android进阶之旅------>修改Android签名证书keystore的密码、别名alias以及别名密码
- android时间日期选择器,监听
- 《C语言程序设计(第二版新版)》课后练习
- 监控HP服务器CPU温度的脚本
- TCP滑动窗口与拥塞窗口
- 大话离散时间信号处理(二)
- codevs2924数独挑战 深度优先搜索
- 关于SpringMVC上传文件的方法
- springMVC中得到request对象,session对象
- C++符号优先级
- 通过触发器解决统计,count(*)问题
- MyBatis入门09之整合spring
- 【Glassfish调查】获取客户端Addr和Host