题目描述
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的时间大概是
注意要特判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