Description:
题解:
设 ,
若 ,我们先不考虑它。
若 ,则 一定不会与其他有重的,贡献为B。
若 ,设 ,显然对于L一样的贡献是一样。
由于 ,所以问题转换为 ,xy有多少不同取值。
划分一下范围变成问 有多少数满足有至少一组xy=它,这个可以想到用容斥原理做,大概要维护lcm和最小的选了的数。
但是L最大是 ,会超时。
注意 的约数个数不多,也就是说可能的lcm个数不多,于是按DAG顺序dp,复杂度就降了下来。
还有一种想法是分块考虑。
枚举i,当前块是
扫描二维码关注公众号,回复:
2219879 查看本文章
显然只有 的才会对它们产生影响,若一数是 的倍数,则这个数可以。
当时复杂度好像还是 ,若 中有两数d1、d2,满足 ,显然只用保留d1,最大的话还剩15个数。
Code:
#include<cstdio>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const int M = 100000;
int bz[M + 5], p[M + 5], u[M + 5];
int n, m, s[100];
ll ans, sum;
int gcd(ll x, ll y) {return !y ? x : gcd(y, x % y);}
void Shai() {
fo(i, 2, M) {
if(!bz[i]) p[++ p[0]] = i, u[i] = i;
fo(j, 1, p[0]) {
int k = i * p[j];
if(k > M) break;
bz[k] = 1; u[k] = p[j];
if(i % p[j] == 0) break;
}
}
u[1] = 1;
}
void dg(int x, int y, int z) {
if(z == 1) return;
ans --;
fo(j, y, p[0]) {
int k = 1;
for(ll u = (ll) x * p[j]; u <= n; u *= p[j], k ++)
dg(u, j + 1, gcd(k, z));
if(k == 1) return;
}
}
int t, w[M], bx[M];
void dfs(int x, ll lcm, int fu) {
if(x > w[0]) {
if(lcm == 1 && fu == -1) return;
sum += fu * ((ll) t * m / lcm - (ll) (t - 1) * m / lcm);
return;
}
dfs(x + 1, lcm, fu);
dfs(x + 1, lcm * w[x] / gcd(lcm, w[x]), -fu);
}
int main() {
Shai();
scanf("%d %d", &n, &m);
ans = n;
dg(1, 1, 0);
ans = ans * m; ans ++;
fo(i, 2, M) if(i * i <= n) {
int x = i, gd = 0;
while(x > 1) {
int y = u[x], z = 0;
while(x % y == 0) x /= y, z ++;
gd = gcd(gd, z);
}
x = 1; int y = 0;
while((ll) x * i <= n) x *= i, y ++;
if(gd == 1) {
ans -= m;
s[y] ++;
}
} else break;
fo(i, 2, 29) if(s[i]) {
sum = 0;
fo(j, 1, i) {
t = j; w[0] = 0;
fo(k, j, i) bx[k] = 0;
fo(k, j, i) if(!bx[k]) {
w[++ w[0]] = k;
fo(o, 1, i / k) bx[o * k] = 1;
}
dfs(1, 1, -1);
}
ans += sum * s[i];
}
printf("%lld\n", ans);
}