关于查找倍数、公因数 优化时间复杂度 有两个很有意思的点
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pdd pair<double, double>
#define pll pair<ll, ll>
#define endl '\n'
#define mp make_pair
#define M(x) x%=mod,x+=mod,x%=mod;
#define FOR(i,j,k) for(int i=(j);i<=(k);i++)
#define ROF(i,j,k) for(int i=(j);i>=(k);i--)
#define ANS cout<<ans<<endl;
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define Yes cout<<"Yes"<<endl;
#define No cout<<"No"<<endl;
typedef long long ll;
ll n,m,x;
inline void solve()
{
cin>>n>>m;
vector<ll> a(n+1),b(n+1),c(n+1),reva(n+1);
FOR(i,1,n){
cin>>a[i];
reva[a[i]]=i;
}
FOR(i,1,n){
cin>>b[i];
}
FOR(i,1,n){
cin>>c[i];
}
vector<ll> g(n+1,0),f(n+1,0);
vector<int> p[n+1];
FOR(i,2,n){
for(int j=1;j*i<=n;j++){
p[j*i].push_back(i);
}
}
vector<ll> jud(n+1,n+1);
ROF(x,n,1){
int idx=n+1;
for(int i:p[b[x]]){
if(idx>jud[i]){
//获取了有同样公因子的后面的数,
idx=jud[i];//而且获取的是下标最小的数,
//符合题意找b[i]下标最小的数
}
}
if(idx==n+1){
f[x]=b[x];
}else{
f[x]=__gcd(b[x],b[idx]);
}
for(int i:p[b[x]]){
jud[i]=x;
}
}
FOR(x,1,n){
for(int i=1;i*x<=n;i++){
if(reva[i*x]>=c[x])g[x]++;//直接遍历倍数,而不是遍历所有找倍数
}
}
while(m--){
cin>>x;
cout<<g[f[x]]<<endl;
}
}
int main()
{
cout << fixed << setprecision(10);
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
solve();
return 0;
}