最大模数

题面:

给你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}}{\rfloor}*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}}{\rfloor}$的值都相等(等于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 }

 

posted @ 2018-07-12 11:48  hehe_54321  阅读(220)  评论(0编辑  收藏  举报
AmazingCounters.com