我刚开始是这样写的:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
int n;cin>>n;
int ans=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(a[i]/j==a[j]/i){
ans++;
}
}
}cout<<ans<<"\n";
return 0;
}
答案错了:
Debug
通过监视我们发现:
当,的时候,编译器进行了向下取整,使得它们的值都为,因此计数器++;
为了消除除法带来的精度问题我们将其转换为乘法,即可以转换为,修改完代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
int n;cin>>n;
int ans=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(a[i]*i==a[j]*j){
ans++;
}
}
}cout<<ans<<"\n";
return 0;
}
运行结果正确,但是运行时长跑了4秒多:
因为数据范围是1e5,而我们写了两层循环。
为了提高效率,只能用一个for循环:
我们用一个map统计 的出现次数,
最后map里面存储的就是所有二元组的个数,最后我们可以使用高斯求和公式求出map里面存放的所有二元组的个数,代码如下:
注意,这个用法是c++17的用法,所以需要升级一下编译器环境。
#include <iostream>
#include<map>
using namespace std;
const int N = 1e5 + 9;
int a[N];
map<int, int>mapp;
int main()
{
int n; cin >> n;
int ans = 0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
mapp[a[i] * i]++;
}
for (auto& [x, y] : mapp)
{
ans += y * (y - 1) / 2;
}
cout << ans << "\n";
return 0;
}
或者不想用c++17的语法也可以这样:
for (auto& it : mapp)
{
int y=it.second;
ans += y * (y - 1) / 2;
}
cout << ans << "\n";
但是这个代码提交之后通过不了:
原因是每个数据都是1e5,一共有1e5个数据,假设i=1e5,a[i]=1e5。那么就会爆int。
因此我们需要开longlong,开完之后就可以过了: