勇敢勇敢我的朋友(题解:P8912)
Senior_Young · · 题解
本题教会了我们,有时看似暴力的做法,实则优化一下就能跑进 1.00s 以内。
我们勇敢地去枚举
然后我们设目前枚举到的
考虑优化。我们可以发现,设
分析一下,因为我们加上了判断,所以我们的
上代码:
#include<bits/stdc++.h>
#define int long long//不开long long见祖宗
using namespace std;
const int N=1e6+5;
int r[N],a[N];
int n,m;
//
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){
char c=getchar();int x=0;bool f=0;
for(;!isdigit(c);c=getchar())f^=!(c^45);
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
if(f)x=-x;return x;
}
//上面的是快读
int query(int x,int y,int p,int q){//计算区间的并
x=max(x,p);y=min(y,q);
return max(y-x+1,0ll);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
r[a[i]]++;
}
m=a[n];
for(int i=1;i<=m;i++){
r[i]+=r[i-1];
}
int ans=0;
for(int x=1;x<=m;x++){
if(r[x-1]==r[x]) continue;//没出现过就跳过
for(int j=1;j<=n;j++){
if(x*j>n+n+m) break;
for(int z=1;z<=m;z++){
int res=x*j*z;
if(res>n+n+m) break;
if(r[z-1]==r[z]) continue;
ans+=query(res-a[j]-r[x],res-a[j]-(r[x-1]+1),r[z-1]+1,r[z]);
}
}
}
cout<<ans;
return 0;
}