传送门:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1026
题解:
其实我并不知道正解是什么,搜索了一晚上没有找到用容斥原理做这道题的方法,思考没有得到结果,可能因为我是正常人吧。
考虑集合分类计数,考虑,将所有的底数
a
分解质因数,质因数的指数为
x1
x2
⋅⋅⋅
xk
,而且个数为
O(logn)
,这时只需要考虑指数有多少种不同的值就好了,我们暴力求解,开一个
bool
数组,这一步是
O(nlog2n)
的,然后就把
a
扫一遍统计答案了,这一步复杂度是
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define N 1000000
#define S 18
using namespace std;
typedef long long LL;
LL ans,m,n,a,b,num,sum,t[N + 5],f[N + 5],g[S + 5][S + 5],l[N + 5],r[N + 5];
bool vis[N * S + 5],flag[N + 5];
inline void get_g(){
for (int i = 1;i <= S; ++i){
sum = 0;
memset(vis,0,sizeof(vis));
for (int j = i;j <= S; ++j){
for (int p = b;p < b + m; ++p)
if (!vis[p * j]) { ++sum; vis[p * j] = 1;}
g[i][j] = sum;
}
}
}
inline void init(){
scanf("%lld%lld%lld%lld",&m,&n,&a,&b);
memset(f,0,sizeof(f));
memset(flag,0,sizeof(flag));
for (LL i = 2;i <= N; ++i)
if (!flag[i]){
num = 1;
for (LL j = i;j <= N;j *= i){
if (j != i) flag[j] = 1;
f[j] = num;
t[j] = i;
++num;
}
}
get_g();
for (int i = a;i < n + a;++i)
if (!l[t[i]]) l[t[i]] = f[i];
for (int i = n + a - 1;i >= a;--i)
if (!r[t[i]]) r[t[i]] = f[i];
ans = 0;
for (int i = 1;i < n + a; ++i)
if (!flag[i]) ans = (ans + g[l[i]][r[i]]);
}
int main(){
init();
cout<<ans;
return 0;
}
注意:1.循环变量优势会爆int
2.bool的内存是int 的1/4,不要算错了