jzoj6027. 【GDOI2019模拟2019.2.23】签到

版权声明:233 https://blog.csdn.net/gmh77/article/details/88790571

题目描述

Description
在这里插入图片描述
Input
在这里插入图片描述
Output
在这里插入图片描述
Sample Input
20 1 4
3
0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Sample Output
9
Data Constraint
在这里插入图片描述

100%

min_25筛裸题(迫真)
设出席的次数为a|b|c(a表示x是否是ai的倍数,b表示x是否是m的倍数,c表示f(x)是否为1,分别是三个函数)
答案就是n-a|b|c
但a|b|c不好直接求,考虑容斥
a|b|c=a+b+c-a&b-a&c-b&c+a&b&c
发现a不能求(a不是积性函数,随便手玩几个数就可以得出),考虑求a的补集a’
则a|b|c=(n-a’)+b+c-(b-a’&b)-(c-a’&c)-b&c+(b&c-a’&b&c)
=n-a’+a’&b+a’&c-a’&b&c

这样a’和a’&c就很好求了,a’的质数前缀和是质数个数-范围内a的个数,a’&c就乘上r[1](f§=f(p^1)=r[1])
单个的函数值可以二分判断+记忆化
如果不记忆化怕不是会T上天

问题1

然后有个van♂题,就是a’&b的求法
可以发现b也不是积性函数,所以a’&b不太好算
但仔细思考可以发现,如果b是某个ai的倍数,那么a’&b一定全部0
如果b不是任何一个ai的倍数,那么b不会影响到答案
因为合法的x都是b的倍数,设x=b*y,则b mod ai!=0
而且ai是质数,说明b中没有ai这个质因子,ai只可能来自于y
所以x mod ai是否等于0只与y有关,把n除以b再算就可以了

问题2

还有一个dark♂van♂题,x=b*y在a’&b中b不会造成影响,但在a’&b&c中要考虑b的函数值
有可能gcd(b,y)>1,这样就有公共的因子,计算f(pc)时要把两个指数相加
一种的解决方法是预处理出所有f值为0的质数,显然除了b的质因子外的质数的求法和a’&b一样,所以只需要处理b的质因子,把不合法的丢进去二分,之后和a’&b做法一样,只不过要考虑b的质因子的幂次
因为要把所有质数都考虑一遍,所以要用递推


还有一种非(shi)常(fen)简(sha)单(bi)的做法,先不考虑b中质因子,计算出√n个前缀和再做一遍dp把b中质因子补上去,同样要用递推
每多一个质因子就会多√n次计算,dp的时间大概是 O ( n log n ) O(\sqrt{n}\log n)

注意要特判n<b的情况

递推写法

https://blog.csdn.net/gmh77/article/details/88142031

code

十分清真
最后是两组测试数据,答案都是0

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
#define sqr(x) ((x)*(x))
using namespace std;

long long g[100011];
long long G[100011];
long long g2[100011];
long long G2[100011];
long long a[100011];
long long b[100011];
long long p[100011];
bool r[61];
long long sum[2][100011];
long long Sum[100011];
long long Get[2][100011];
long long Get2[2][100011];
bool bz[100011];
bool Bz[100011];
int tot[100011];
long long d[101][2];
long long n,N,m,B,S;
int i,j,k,l,sq,Sq,len,Len;
long long ans;
bool bz2;

int get(long long x) //aÖÐÓжàÉÙ¸öÊý¡Üx
{
	int l=1,r=m,mid;
	
	if (!m) return 0;
	
	if (x<=Sq)
	{
		if (Get[0][x]>=0)
		return Get[0][x];
	}
	else
	{
		if (Get[1][n/x]>=0)
		return Get[1][n/x];
	}
	
	while (l<r)
	{
		mid=(l+r)/2;
		
		if (a[mid]<=x) l=mid+1;
		else
		r=mid;
	}
	l+=(a[l]<=x);
	
	if (x<=Sq)
	Get[0][x]=l-1;
	else
	Get[1][n/x]=l-1;
	
	return l-1;
}

int get2(long long x) //BµÄÖÊÒò×ÓÖÐÓжàÉÙ¸öÊý¡Üx
{
	int l=1,r=Len,mid;
	
	if (!Len) return 0;
	
	if (x<=Sq)
	{
		if (Get2[0][x]>=0)
		return Get2[0][x];
	}
	else
	{
		if (Get2[1][n/x]>=0)
		return Get2[1][n/x];
	}
	
	while (l<r)
	{
		mid=(l+r)/2;
		
		if (d[mid][0]<=x) l=mid+1;
		else
		r=mid;
	}
	l+=(d[l][0]<=x);
	
	if (x<=Sq)
	Get2[0][x]=l-1;
	else
	Get2[1][n/x]=l-1;
	
	return l-1;
}

bool pd(long long x) //ÅжÏxÊÇ·ñÔÚaÖÐ
{
	return Bz[x];
}

long long f(long long p,int e,int bz) //s=p^e,p is a prime
{
	switch (bz)
	{
		case 0:{
			return !pd(p);
			break;
		}
		case 1:{
			return !pd(p) && (r[e] || p==1);
			break;
		}
	}
}

bool F(long long p,int e) //s=p^e,p is a prime
{
	return r[e];
}

void init_B()
{
	int i;
	S=B;
	
	fo(i,1,len)
	if (!(S%p[i]))
	{
		++Len;
		d[Len][0]=p[i];
		
		while (!(S%p[i]))
		{
			S/=p[i];
			++tot[p[i]];
			++d[Len][1];
		}
	}
	
	if (S>1)
	{
		++Len;
		d[Len][0]=S;
		d[Len][1]=1;
	}
}

void init()
{
	long long S,P;
	int _i,j,k,l;
	
	memset(Get,255,sizeof(Get));
	memset(bz,0,sizeof(bz));
	sq=floor(sqrt(n));Sq=n/sq;
	if (!bz2) --Sq;
	
	fo(i,1,sq) b[i]=n/i;
	len=0;
	
	fo(i,1,Sq) g[i]=i-1;
	fo(i,1,sq) G[i]=b[i]-1;
	
	fo(_i,2,sq)
	{
		if (!bz[_i])
		{
			p[++len]=_i;
			P=sqr(p[len]);
			
			fo(i,1,sq)
			if (b[i]>=P)
			{
				S=b[i]/_i;
				
				if (S<=Sq)
				G[i]=G[i]-(g[S]-g[_i-1]);
				else
				G[i]=G[i]-(G[n/S]-g[_i-1]);
			}
			else
			break;
			fd(i,Sq,1)
			if (i>=P)
			{
				S=i/_i;
				g[i]=g[i]-(g[S]-g[_i-1]);
			}
			else
			break;
		}
		
		fo(j,1,len)
		if (p[j]*_i<=sq)
		{
			bz[p[j]*_i]=1;
			
			if (!(_i%p[j]))
			break;
		}
		else
		break;
	}
	
	fo(i,1,len)
	{
		fo(j,0,1)
		sum[j][i]=sum[j][i-1]+f(p[i],1,j);
	}
}

long long dfs(long long s,int j,int bz)
{
	long long S,P,s2;
	int i,k,l,e;
	bool Tot=1;
	
	switch (bz)
	{
		case 0:{ //a' or a'b
			if (s<=Sq)
			S=g[s];
			else
			S=G[n/s];
			S-=get(s);
			
			break;
		}
		case 1:{ //a'c
			if (s<=Sq)
			S=g[s];
			else
			S=G[n/s];
			S-=get(s);
			S*=r[1];
			
			break;
		}
	}
	S-=sum[bz][j-1];
	
	fo(k,j,len)
	if (sqr(p[k])<=s)
	{
		e=1;
		s2=s/p[k];
		P=1;
		
		while (s2)
		{
			P*=p[k];
			
			if (k<len && p[k+1]<=s2 || k==len && p[len]<s2)
			S+=f(p[k],e,bz)*dfs(s2,k+1,bz);
			if (e>1)
			S+=f(p[k],e,bz);
			
			++e;
			s2/=p[k];
		}
	}
	else
	break;
	
	if (j==1)
	S+=f(1,1,bz);
	
	return S;
}

void Init() //a'bc
{
	long long S,P,p2,e;
	int _i,i,j,k,l;
	
	memset(Get2,255,sizeof(Get2));
	
	fo(i,1,Sq) g[i]=(g[i]-(get(i)+get2(i)))*r[1],g2[i]=g[i];
	fo(i,1,sq) G[i]=(G[i]-(get(b[i])+get2(b[i])))*r[1],G2[i]=G[i];
	
	fd(_i,len,1)
	if (!tot[p[_i]] && !pd(p[_i]))
	{
		fo(i,1,sq)
		if (b[i]>=sqr(p[_i]))
		{
			p2=p[_i];e=1;
			
			while (b[i]/p[_i]>=p2)
			{
				S=b[i]/p2;
				
				if (S<=Sq)
				G2[i]+=F(p[_i],e)*(g2[S]-g[p[_i]])+F(p[_i],e+1);
				else
				G2[i]+=F(p[_i],e)*(G2[n/S]-g[p[_i]])+F(p[_i],e+1);
				
				++e;
				p2*=p[_i];
			}
		}
		else
		break;
		fd(i,Sq,1)
		if (i>=sqr(p[_i]))
		{
			p2=p[_i];e=1;
			
			while (i/p[_i]>=p2)
			{
				S=i/p2;
				
				g2[i]+=F(p[_i],e)*(g2[S]-g[p[_i]])+F(p[_i],e+1);
				
				++e;
				p2*=p[_i];
			}
		}
		else
		break;
	}
}

void dp()
{
	long long p,S,s;
	int i,j,k,l,e;
	
	fo(i,1,Sq) ++g2[i];
	fo(i,1,sq) ++G2[i];
	
	fo(i,1,Len)
	{
		fo(j,1,sq)
		{      
			p=1;
			e=d[i][1];
			
			s=0;
			while (1)
			{
				S=b[j]/p;
				
				if (S<=Sq)
				s+=F(d[i][0],e)*g2[S];
				else
				s+=F(d[i][0],e)*G2[n/S];
				
				if (b[j]/d[i][0]>=p)
				{
					p*=d[i][0];
					++e;
				}
				else
				break;
			}
			G2[j]=s;
		}
		fd(j,Sq,1)
		{
			p=1;
			e=d[i][1];
			
			s=0;
			while (1)
			{
				S=j/p;
				
				s+=F(d[i][0],e)*g2[S];
				
				if (j/d[i][0]>=p)
				{
					p*=d[i][0];
					++e;
				}
				else
				break;
			}
			g2[j]=s;
		}
	}
}

int main()
{
	freopen("qiandao.in","r",stdin);
	freopen("qiandao.out","w",stdout);
	
	scanf("%lld%d%lld",&n,&m,&B);
	
	j=floor(sqrt(n));
	fo(i,1,m)
	{
		scanf("%lld",&a[i]);
		if (a[i]<=j)
		Bz[a[i]]=1;
		
		if (!(B%a[i]))
		bz2=1;
	}
	r[0]=1;
	fo(i,1,60)
	scanf("%d",&r[i]);
	
	init();
	init_B();
	
	ans=n-dfs(n,1,0)+dfs(n,1,1);
	
	if (!bz2 && n>=B)
	{
		N=n;
		n/=B;
		
		init();
		ans=ans+dfs(n,1,0);
		
		Init();
		dp();
		
		ans=ans-G2[1];
		n=N;
	}
	
	printf("%lld\n",n-ans);
	
	fclose(stdin);
	fclose(stdout);
	
	return 0;
}
//
//16 1 1
//5
//1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
//
//20 3 1
//7 11 19 
//1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

猜你喜欢

转载自blog.csdn.net/gmh77/article/details/88790571