设是a[i]的倍数的限制为a,是b的倍数限制为b,f=1的限制为c。
相当于求:
a|b|c
=a+b+c-a&b-a&c-b&c+a&b&c
发现我们求a并不好求,考虑把所有的a改成!a
=(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[i]都是质数,所以可以看做一个积性函数, f ( p q ) = [ p ∉ a ] f(p^q)=[p∉a] f(pq)=[p∈/a],然后可以min_25筛。
!a&b同理。
!a&c也是差不多的。
!a&b&c的话,如果f(b)=0,要把b补成合法的,然后也是差不多的。
代码较繁琐。
Code:
#include
#include
#include
#include
#define db double
#define pp printf
#define ll long long
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
using namespace std;
const int N = 2e5 + 5;
ll n, b, a[N];
int a0, r[61];
int f[N * 10], bz[N * 10];
ll u[20]; int v[20], u0;
int p[N];
ll g[N], h[N], w[N], sp[N];
int i1[N], i2[N];
ll ans; int m, sqr;
int t[N], c[N];
void sieve(int n) {
fo(i, 1, n) bz[i] = 0; p[0] = 0;
fo(i, 2, n) {
if(!bz[i]) {
p[++ p[0]] = i;
sp[p[0]] = sp[p[0] - 1] + !t[i];
}
for(int j = 1; i * p[j] <= n; j ++) {
bz[i * p[j]] = 1;
if(i % p[j] == 0) break;
}
}
}
ll dg(ll x, int y) {
if(x <= 1 || p[y] > x) return 0;
int k = x <= sqr ? i1[x] : i2[n / x];
ll s = g[k] - sp[y - 1];
for(int i = y; i <= p[0] && (ll) p[i] * p[i] <= x; i ++) {
ll p1 = p[i], p2 = (ll) p[i] * p[i];
if(!t[p1])
for(int e = 1; p2 <= x; e ++, p1 = p2, p2 *= p[i])
s = s + dg(x / p1, i + 1) + 1;
}
return s;
}
ll dd(ll x, int y) {
if(x <= 1 || p[y] > x) return 0;
int k = x <= sqr ? i1[x] : i2[n / x];
ll s = h[k] - (r[1] ? sp[y - 1] : 0);
for(int i = y; i <= p[0] && (ll) p[i] * p[i] <= x; i ++) {
ll p1 = p[i], p2 = (ll) p[i] * p[i];
if(!t[p1])
for(int e = 1; p2 <= x; e ++, p1 = p2, p2 *= p[i])
s = s + dd(x / p1, i + 1) * r[e] + r[e + 1];
}
return s;
}
void g1(ll n) {
int m = 0;
sqr = sqrt(n); sieve(sqr);
for(ll i = 1, j; i <= n; i = j + 1) {
j = n / (n / i); w[++ m] = n / i;
if(w[m] <= sqr) i1[w[m]] = m; else i2[n / w[m]] = m;
g[m] = w[m] - 1;
}
fo(j, 1, p[0]) for(int i = 1; i <= m && (ll) p[j] * p[j] <= w[i]; i ++) {
int k = (w[i] / p[j] <= sqr) ? i1[w[i] / p[j]] : i2[n / (w[i] / p[j])];
g[i] = g[i] - (g[k] - (j - 1));
}
int x = a0;
fo(i, 1, m) {
while(a[x] > w[i] && x > 0) x --;
g[i] -= x;
if(r[1]) h[i] = g[i]; else h[i] = 0;
}
ans += n - (dg(n, 1) + 1);
ans += dd(n, 1) + 1;
}
int ky = 1;
void g3(ll n) {
int m = 0;
sqr = sqrt(n); sieve(sqr);
for(ll i = 1, j; i <= n; i = j + 1) {
j = n / (n / i); w[++ m] = n / i;
if(w[m] <= sqr) i1[w[m]] = m; else i2[n / w[m]] = m;
g[m] = w[m] - 1;
}
fo(j, 1, p[0]) for(int i = 1; i <= m && (ll) p[j] * p[j] <= w[i]; i ++) {
int k = (w[i] / p[j] <= sqr) ? i1[w[i] / p[j]] : i2[n / (w[i] / p[j])];
g[i] = g[i] - (g[k] - (j - 1));
}
int x = a0;
fo(i, 1, m) {
while(a[x] > w[i] && x > 0) x --;
g[i] -= x;
}
ans += dg(n, 1) + 1;
}
void sieve2(int n) {
fo(i, 1, n) bz[i] = 0; p[0] = 0;
fo(i, 2, n) {
if(!bz[i]) {
p[++ p[0]] = i;
sp[p[0]] = sp[p[0] - 1] + (c[i] ? r[1 + c[i]] : (t[i] ? 0 : r[1]));
}
for(int j = 1; i * p[j] <= n; j ++) {
bz[i * p[j]] = 1;
if(i % p[j] == 0) break;
}
}
}
ll dg2(ll x, int y) {
if(x <= 1 || p[y] > x) return 0;
int k = x <= sqr ? i1[x] : i2[n / x];
ll s = g[k] - sp[y - 1];
for(int i = y; i <= p[0] && (ll) p[i] * p[i] <= x; i ++) {
if(t[p[i]]) continue;
ll p1 = p[i], p2 = (ll) p[i] * p[i];
int e = 1; if(c[p1]) e += c[p1];
for(; p2 <= x; e ++, p1 = p2, p2 *= p[i])
s = s + (ll) dg2(x / p1, i + 1) * r[e] + r[e + 1];
}
return s;
}
void g2(ll n) {
int m = 0;
sqr = sqrt(n); sieve2(sqr);
for(ll i = 1, j; i <= n; i = j + 1) {
j = n / (n / i); w[++ m] = n / i;
if(w[m] <= sqr) i1[w[m]] = m; else i2[n / w[m]] = m;
g[m] = w[m] - 1;
}
fo(j, 1, p[0]) for(int i = 1; i <= m && (ll) p[j] * p[j] <= w[i]; i ++) {
int k = (w[i] / p[j] <= sqr) ? i1[w[i] / p[j]] : i2[n / (w[i] / p[j])];
g[i] = (g[i] - g[k] + (j - 1));
}
int x = a0;
fo(i, 1, m) {
while(a[x] > w[i] && x > 0) x --;
if(!r[1]) g[i] = 0;
fo(j, 1, u0) if(u[j] <= w[i])
g[i] += r[v[j] + 1] - r[1];
g[i] -= x * r[1];
}
ans -= dg2(n, 1) + 1;
}
ll n0;
int main() {
freopen("qiandao.in", "r", stdin);
freopen("qiandao.out", "w", stdout);
scanf("%lld %d %lld", &n, &a0, &b);
fo(i, 1, a0) scanf("%lld", &a[i]);
fo(i, 1, 60) scanf("%d", &r[i]);
sort(a + 1, a + a0 + 1); a0 = unique(a + 1, a + a0 + 1) - (a + 1);
fo(i, 1, a0) if(a[i] <= 1e5) t[a[i]] = 1;
g1(n); n0 = n;
fo(i, 1, a0) if(b % a[i] == 0) ky = 0;
if(ky && n >= b) {
n /= b;
g3(n);
n = n0;
{
ll x = b;
fo(i, 2, 2e5) if(x % i == 0) {
u[++ u0] = i;
while(x % i == 0) x /= i, v[u0] ++;
}
if(x > 1) u[++ u0] = x, v[u0] = 1;
}
fo(i, 1, u0) if(!r[v[i]]) {
while(!r[v[i]] && b <= n) v[i] ++, b *= u[i];
}
fo(i, 1, u0) if(u[i] <= 1e5) c[u[i]] = v[i];
if(n >= b) {
n /= b, g2(n);
}
}
pp("%lld", n0 - ans);
}