题解讲的非常清楚,写个题解加深一下自己的印象
对原题抽象、建模后,对于每个的操作其实就是若干个一次函数
,求满足
的i的数量。
等式变完形后就是,显然对于该
的操作,会爆炸的村庄需要满足以下两个条件:
1.
2.
所以大致思路就是枚举的因子
,确定
,然后判断距离为
的村庄
是否等于
接着处理几个细节,用调和级数预处理出的倍数,建立一颗数
指向所有因子的森林,在枚举
因子时可以
。
时需要特判,因为没有存0的因子
相同的村庄只有两个,桶排一下。
MyCode:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+7,maxm=1e6*25,mod=1e9+7;
typedef long long int ll;
typedef unsigned long long ull;
int head[maxn],Next[maxm],to[maxm],tot,n,m,x,a[maxn][2];
inline void add(int x,int y) {
to[++tot]=y;
Next[tot]=head[x];
head[x]=tot;
}
inline void preint() {
for(int i=1; i<=1000000; ++i)
for(int j=i; j<=1000000; j+=i)
add(j,i);
for(int i=1,y,j; i<=n; ++i) {
cin>>y;
if(a[j=abs(i-x)][0]) a[j][1]=y;
else a[j][0]=y;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>m>>x;
preint();
int op,h,t,ans(0);
while(m--) {
cin>>op>>h;
if(op&1) {
cin>>t;
if(!t) {
if(!h) {
ans+=1;
continue;
}
if(x+h<=n) ans+=1;
if(x-h>=1) ans+=1;
continue;
}
for(int i=head[t],y=to[i],dis; i; i=Next[i],y=to[i]) {
dis=h-t/y;
if(dis<0) continue;
if(a[dis][0]==y) ans+=1;
if(a[dis][1]==y) ans+=1;
}
} else {
cout<<ans<<'\n';
cout.flush();
}
}
return 0;
} 
京公网安备 11010502036488号