zoukankan      html  css  js  c++  java
  • 最大模数

    题面:

    给你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 }
  • 相关阅读:
    Fragment传参
    android手机旋转方向识别
    如何激活已经运行过的Activity, 而不是重新启动新的Activity
    Android 在Canvas中实现画笔效果(一)--钢笔
    [AS3]as3画笔实例实现橡皮擦功能源代码
    在 Windows 環境下利用 VNC 遠端控管 Mac OS X Server
    mac下开发IOS代码管理
    Android开发--仿微信语音对讲录音
    Android 二维码 生成和识别(附Demo源码)
    Android开源项目分类汇总
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9298467.html
Copyright © 2011-2022 走看看