SPOJ 4491

不妨先把所有要求的素数的对的个数写出来

f(2)=u(1)G(2)+u(2)*G(2*2)+u(3)*G(2*3)+.....u(k2)*G(2*k2)

f(3)=u(1)G(3)+u(2)*G(2*3)+u(3)*G(3*3)+.....u(k3)*G(3*k3)

....

f(p)=u(1)G(p)+u(2)*G(2*p)+u(3)*G(p*3)+.....u(kp)*G(p*kp)

相加之后

会发现,其实G的变量是从1~n的。于是,最重要便 是求出其合并后的系数了。怎么样求呢?我不懂,看了看别人的,发现竟有这样一个等式

于是,在线性筛选法上加上相关语句就可以求到相应的系数了。线性筛选:

http://wenku.baidu.com/link?url=ufaT0myBu70JxfkYUDsAtgPin6Y4uI8DwU43QCiQoqOOY9xhJJg3jr6DVn24sF2mAXRYrM6Hjrai-vMwfQ7-5IbQVDqwCGIwVzZR6xMVxiq

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 10000005

using namespace std;
typedef long long LL;

bool check[N];
int mu[N],tot;
int prime[N],he[N];

void initial(){
	memset(check,false,sizeof(check));
	memset(he,0,sizeof(he));
	mu[1]=1;
	tot=0;
	for(LL i=2;i<N;i++){
		if(!check[i]){
			prime[tot++]=i;
			he[i]=1;
			mu[i]=-1;
		}
		for(LL j=0;j<tot;j++){
			if(i*prime[j]>N) break;
			check[i*prime[j]]=true;
			if(i%prime[j]==0){
				mu[i*prime[j]]=0;
				he[i * prime[j]] = mu[i];
				break;
			}
			else{
				he[i*prime[j]] = mu[i] - he[i];  

				mu[i*prime[j]]=-mu[i];
			}
		}
	}
	for(int i=2;i<N;i++)
	he[i]+=he[i-1];
}

LL slove(int tx,int ty){
	if(tx>ty) swap(tx,ty);
	int l=1,r,p1,p2;
	LL ans=0;
	while(l<=tx){
		r=min(min(tx/(p1=tx/l),ty/(p2=ty/l)),tx);
		ans+=((LL) p1*(LL )p2*(LL )(he[r]-he[l-1]));
		l=r+1;
	}
	return ans;
}

int main(){
	initial();
	int T;
	scanf("%d",&T);
	int x,y,tx,ty;
	LL ans;
	while(T--){
		scanf("%d%d",&x,&y);
		ans=slove(x,y);
		printf("%lld\n",ans);
	}
	return 0;
}

  

时间: 2024-08-07 16:45:54

SPOJ 4491的相关文章

spoj 4491 莫比乌斯反演

题意: 给出a,b,求gcd(x,y)=prime的方案数,其中:1 <= x <= a && 1 <= y <= b 限制: 1 <= a,b <= 1e7 思路: 先把问题拆成一个一个来考虑,然后问题就变成gcd(x,y)=k的方案数. 设f(k)为gcd(x,y)=k的方案数, 设F(k)为gcd(x,y)为k的倍数的方案数,显然F(k)=floor(a/k)*floor(b/k). 由莫比乌斯反演得: f(k)=mu[1]*F[k]+mu[2]*

bzoj 2818: Gcd GCD(a,b) = 素数

2818: Gcd Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1566  Solved: 691[Submit][Status] Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sample Output 4 HINT hint 对于样例(2,2),(2,4),(3,3),(4,2) 1<=N<=

SPOJ 705 Distinct Substrings(后缀数组)

[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每个后缀对答案的贡献为n-sa[i]+1-h[i], 因为排名相邻的后缀一定是公共前缀最长的, 那么就可以有效地通过LCP去除重复计算的子串. [代码] #include <cstdio> #include <cstring> #include <algorithm> usi

SPOJ 3273

传送门: 这是一道treap的模板题,不要问我为什么一直在写模板题 依旧只放代码 1 //SPOJ 3273 2 //by Cydiater 3 //2016.8.31 4 #include <iostream> 5 #include <cstring> 6 #include <ctime> 7 #include <cmath> 8 #include <cstdlib> 9 #include <string> 10 #include

SPOJ CRAN02 - Roommate Agreement

题目链接:http://www.spoj.com/problems/CRAN02/ 题目大意:N个数字组成的序列,和为0的连续子序列的个数.N<1e6 解题思路:计算前缀和,统计每个数字出现的次数,那么对于数字sum[i], 如果存在k个sum[i],则代表有C(k, 2)个序列和为0,而如果sum[i] = 0,则还要累加上对应的k值. 代码: 1 ll n; 2 int a[maxn]; 3 ll sum[maxn]; 4 map<int, int> mmp; 5 6 void so

spoj GCJ1C09C Bribe the Prisoners

题目链接: http://www.spoj.com/problems/GCJ1C09C/ 题意: In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Cells number i and i+1 are adjacent, and prisoners in adjacent cells are called "neighbours." A wall wi

SPOJ QTREE Query on a tree ——树链剖分 线段树

[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 20005 int T,n,fr[maxn],h[maxn],to[maxn],ne[maxn]

BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca

2588: Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数表示点i的权值. 后面N-1行每行两个整数(x,y),表示点x到点y有一条边. 最后M行每行两个整数(u,v,k),表示一组询问.

BZOJ 1002 + SPOJ 104 基尔霍夫矩阵 + 一个递推式。

BZOJ 1002 高精度 + 递推 f[1] = 1; f[2] = 5; f[i] = f[i - 1] * 3 - f[i - 2] + 2; SPOJ 104 裸 + 不用Mod 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std;