题目

【JZOJ 杂题选讲】牛牛喜欢看小姐姐_题组

思路

考虑从a[1…n]枚举s个出来,求lcm,答案就是所有lcm倍数的并

一共有C(n,s)个lcm的倍数集合,选i个出来,取交,也就是所有lcm的lcm,容斥系数是(−1)i−1。

不管怎样,lcm都是m的约数

考虑枚举d|m,那么只需要算出lcm的lcm是它情况的容斥系数和就好了,记为f[d]

ans=f[d]*(k/d)

代码

#include<bits/stdc++.h>
#define fo(i,x,y) for(int i = x,_b = y; i <= _b; i ++)
#define ff(i,x,y) for(int i = x,_b = y; i <  _b; i ++)
#define fd(i,x,y) for(int i = x,_b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int N = 2e5 + 77;

ll n,m,k,s;
ll a[N];

ll gcd(ll x,ll y) {
	return !y ? x : gcd(y,x % y);
}

ll mul(ll x,ll y,ll mo) {
	x %= mo,y %= mo;
	ll z = (long double) x * y / mo;
	z = x * y - z * mo;
	if(z < 0) z += mo; else if(z >= mo) z -= mo;
	return z;
}

ll ksm(ll x,ll y,ll mo) {
	ll s = 1;
	for(; y; y /= 2,x = mul(x,x,mo))
		if(y & 1) s = mul(s,x,mo);
	return s;
}

int pd_p(ll n) {
	if(n == 2) return 1;
	if(n % 2 == 0) return 0;
	ll s = n - 1,c = 0; while(s % 2 == 0) s /= 2,c ++;
	fo(ii,1,40) {
		ll x = ksm(rand() % (n - 1) + 1,s,n);
		fo(i,1,c) {
			ll y = mul(x,x,n);
			if(y == 1 && x != 1 && x != n - 1) return 0;
			x = y;
		}
		if(x != 1) return 0;
	}
	return 1;
}

ll find(ll n) {
	ll x = rand() % (n - 1) + 1,c = rand() % n,y = x;
	ll i = 1,k = 2;
	while(1) {
		x = (mul(x,x,n) + c) % n;
		ll d = gcd(n,abs(y - x));
		if(d != 1 && d != n) return d;
		if(x == y) return 1;
		if((++ i) == k) y = x,k *= 2;
	}
}

ll u[100],v[100],u0;

void fen(ll n) {
	if(n == 1) return;
	if(pd_p(n)) { u[++ u0] = n; return;}
	ll d = find(n);
	fen(d); fen(n / d);
}

void px() {
	sort(u + 1,u + u0 + 1);
	int U = u0; u0 = 0;
	fo(i,1,U) if(!u0 || u[i] != u[u0])
		u[++ u0] = u[i],v[u0] = 1; else v[u0] ++;
}

ll d[200005]; int d0;
void dg(int x,ll y) {
	if(x > u0) {
		d[++ d0] = y;
		return;
	}
	fo(i,0,v[x]) {
		dg(x + 1,y);
		if(i < v[x]) y *= u[x];
	}
}

const int M = 1960817;
ll h[M]; int h2[M];
int ha(ll n) {
	int y = n % M;
	while(h[y] != 0 && h[y] != n)
		y = (y + 1) % M;
	return y;
}
void add(ll n,int x) {
	int y = ha(n);
	h[y] = n; h2[y] = x;
}
int qu(ll n) {
	return h2[ha(n)];
}

ll f[N],g[N];

#define ul unsigned long long

ul yjy(ll s) {
	ul ans = (s <= n ? 1 : 0);
	fo(i,1,d0) g[qu(d[i])] = (f[qu(d[i])] >= s);
	fo(i,1,u0) {
		fd(j,d0,1) if(d[j] % u[i] == 0)
			g[qu(d[j])] -= g[qu(d[j] / u[i])];
	}
	fo(i,1,d0) ans += (ul) g[qu(d[i])] * (k / d[i]);
	return ans;
}

int main() {
	srand(time(NULL));
	scanf("%lld %lld %lld %lld",&n,&m,&k,&s);
	fo(i,1,n) scanf("%lld",&a[i]),a[i] = gcd(a[i],m);
	if(m == 1) {
		pp("%d\n",s == n ? n : 0);
		return 0;
	}
	u0 = 0; fen(m); px();
	dg(1,1);
	sort(d + 1,d + d0 + 1);
	fo(i,1,d0) add(d[i],i);
	fo(i,1,n) f[qu(a[i])] ++;
	fo(i,1,u0) {
		fo(j,1,d0) if(d[j] % u[i] == 0)
			f[qu(d[j])] += f[qu(d[j] / u[i])];
	}
	pp("%llu\n",yjy(s) - yjy(s + 1));
}