枚举,前缀和。
先从小到大排序,然后枚举最小的数字选择哪一个。接下来就是计算比他大的数做出的贡献。因为肯定是连续的一段贡献都是一样的,因此二分一下就可以了。这样$800$多$ms$能水过。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<ctime> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-10; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } int n; long long a[200010],b[200010]; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; b[i]=a[i]+b[i-1]; } sort(a+1,a+1+n); long long ans=0; for(int i=1;i<=n;i++) { if(a[i]==a[i-1]) continue; if(a[i]==1) { ans=max(ans,b[n]-b[i-1]); continue; } long long p=0; int L=i,R=n,pos; while(1) { pos=-1; int tmp=L; while(L<=R) { int mid=(L+R)/2; if(a[mid]/a[i]==a[tmp]/a[i]) pos=mid,L=mid+1; else R=mid-1; } p=p+a[pos]/a[i]*a[i]*(pos-tmp+1); L=pos+1,R=n,pos=-1; if(L>n) break; } ans=max(ans,p); } cout<<ans<<endl; return 0; }
因为可以$O(1)$得到某个范围内的数字有几个,优化了一下,$400$多$ms$能过。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<ctime> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-10; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } int n; long long a[200010],b[400010]; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; b[a[i]]++; } sort(a+1,a+1+n); for(int i=1;i<=400000;i++) b[i]=b[i]+b[i-1]; long long ans=0; for(int i=1;i<=n;i++) { if(a[i]==a[i-1]) continue; long long p=0; for(int j=a[i];j<=a[n];j=j+a[i]) p=p+(b[j+a[i]-1]-b[j-1])*j; ans=max(ans,p); } cout<<ans<<endl; return 0; }