题意是给n个a和b,1<=a,b<=n,问有多少ai*aj==bi+bj,i<j ,2e5的数据规模
看一眼数据规模,a,b都是小于等于n的,意味着如果ai*aj>n那么就对答案无贡献,或者说,对于一个ai,剩下数中可能能对答案产生影响的aj,一定是小于等于n/ai的。
那么我们可以以ai为依据升序排序,先枚举从1到sqrt(n)作为ai,设置一个数组保存bi的数目,然后枚举j,可以很方便地计算ai*aj-bj的数目,如果当前aj==ai的话,说明对应的bi数量++
从小到大排序,避免了第二层循环到j的时候,后面还有可行的ai
现在才知道这玩意叫做“分块”
查看代码
#pragma GCC optimize(2)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
void solve()
{
ll n,ans=0;
cin>>n;
vector<pair<int,int> >a(n);
for(int i=0;i<n;i++)
cin>>a[i].first;
for(int i=0;i<n;i++)
cin>>a[i].second;
sort(a.begin(),a.end());//保证将x=i的y的cnt更新,同时只跑一次避免重复
for(int i=1;i*i<=2*n;i++)
{
vector<int>cnt(n+1);//保存a=i时的b=j时的数量
for(auto [x,y]:a)
{
int bj=x*i-y;
if(bj>=1&&bj<=n)ans+=cnt[bj];//先加再更新避免自加
if(x==i)
cnt[y]++;
}
}
cout<<ans<<"\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)solve();