题面:
给你n个整数,找出一对数$a_i$,$a_j$使得$a_i$%$a_j$最大,($a_i$>=$a_j$)
http://210.33.19.103/problem/3397
http://codeforces.com/problemset/problem/484/B
https://vjudge.net/problem/51Nod-1421
$a_i$%$a_j=a_i-{lfloor}{frac{a_i}{a_j}}{ floor}*a_j$
显然读入以后要排序
可以想到枚举$a_i$,对于每个$a_i$做数论分块,还要预处理一下其他东西,得到一个$n*sqrt(n)$的算法
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #pragma GCC optimize("Ofast") 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 15 int n,a[200100],num[2000100],ans; 16 //num[i]是使得a[j]>=i的最小的j 17 int main() 18 { 19 int k,i,j,kk; 20 scanf("%d",&n); 21 for(i=1;i<=n;i++) scanf("%d",&a[i]); 22 sort(a+1,a+n+1); 23 for(i=1,j=0;i<=1000100;i++) 24 { 25 while(j<=n&&a[j]<i) j++; 26 num[i]=j; 27 } 28 for(kk=1;kk<=n;kk++) 29 { 30 k=a[kk]; 31 for(i=1;i<=k;i=j+1) 32 { 33 j=min(k,k/(k/i)); 34 if(num[i]>num[j+1]-1) continue; 35 ans=max(ans,k-(k/i)*a[num[i]]); 36 } 37 } 38 printf("%d",ans); 39 return 0; 40 }
T飞了。。。
事实上也可以枚举$a_j$,当$k*a_j<=a_i<(k+1)*a_j$时,${lfloor}{frac{a_i}{a_j}}{ floor}$的值都相等(等于k),因此可以考虑枚举$a_j$和$k$
直接这么做的话,会被"前面全是1,最后一个很大"的数据卡成$n^2$...所以排序以后再去一下重就可以了
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #pragma GCC optimize("Ofast") 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 15 int n,a[200100],num[2000100],ans; 16 //num[i]是使得a[j]>=i的最小的j 17 int main() 18 { 19 int k,i,j,l,r; 20 scanf("%d",&n); 21 for(i=1;i<=n;i++) scanf("%d",&a[i]); 22 sort(a+1,a+n+1);n=unique(a+1,a+n+1)-a-1; 23 for(i=1,j=0;i<=2000000;i++) 24 { 25 while(j<=n&&a[j]<i) j++; 26 num[i]=j; 27 } 28 for(j=1;j<=n;j++) 29 { 30 for(k=1;k*a[j]<=a[n];k++) 31 { 32 l=num[k*a[j]];r=num[(k+1)*a[j]]-1; 33 if(l>r) continue; 34 ans=max(ans,a[r]-k*a[j]); 35 } 36 } 37 printf("%d",ans); 38 return 0; 39 }