zoukankan      html  css  js  c++  java
  • CF449C:Jzzhu and Apples

    题意简述

    给出正整数n,你要把1-n之间的正整数分成尽可能多组,使得每一组两个数的最大公约数大于1;输出能分成最多组的个数,并按任意顺序输出每组的两个数.

    很妙的一道题。

    首先我们考虑去处理每个质数的倍数,那么这个质数一定是小于等于 n/2 的,不然它在 n 的范围内是不会有倍数的。

    那么我们先把 $1~n/2$ 范围内的所有质数筛出来。

    枚举质数

    然后我们要怎么用质数去处理答案呢?

    首先我们从大到小枚举这些质数,然后去枚举它的倍数。

    然鹅这样复杂度不会炸么?不会。 $O(sigma_{i=2}^{n/2}n/i)$ 的复杂度吧,而且还远达不到。

    信仰一下应该是过得了的,实际上确实也过了。

    处理倍数

    然后我们再考虑如果这些倍数该怎么处理。

    我们首先看这些倍数有没有被使用过,没有的话就入栈。

    最优性理解

    那么为什么能用就入栈的解法最优呢?

    其实很简单,因为当前枚举那个数可以被当前的质数整除,那么该数与当前枚举质数的倍数去匹配肯定不会产生更劣的结果。

    那么如果有数字剩下来呢?

    如果说当前枚举质数的未使用过的倍数有奇数个,那么我们可以将第 2 个倍数与最后一个换一下,然后弹出栈,标记为未使用。

    为什么这样做能达到最优?

    考虑第二个倍数一定是 2 的倍数,那么把他弹出的话就可以和 2 的倍数去匹配,而且我们每次遇到奇数个的情况都是弹 2 的倍数,那么这些多余的数就可以凑一块儿了。

     1 //by Judge
     2 #include<vector>
     3 #include<cstdio>
     4 #include<iostream>
     5 #define P make_pair
     6 using namespace std;
     7 const int M=1e5+11;
     8 char sr[1<<21],z[20];int C=-1,Z;
     9 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    10 inline void print(int x,char chr='
    '){
    11     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    12     while(z[++Z]=x%10+48,x/=10);
    13     while(sr[++C]=z[Z],--Z);sr[++C]=chr;
    14 } int n,cnt,ans,top,prim[M],is[M],vis[M],num[M];
    15 pair<int,int> tmp[M];
    16 inline void prep(){
    17     for(int i=2;i<=n>>1;++i){
    18         if(!is[i]) prim[++cnt]=i;
    19         for(int j=1;j<=cnt&&i*prim[j]<=n/2;++j){
    20             is[i*prim[j]]|=1;
    21             if(i%prim[j]==0) break;
    22         }
    23     }
    24 }
    25 int main(){
    26     scanf("%d",&n),prep();
    27     for(int i=cnt;i;--i){ top=0;
    28         for(int j=prim[i];j<=n;j+=prim[i])
    29             if(!vis[j]) num[++top]=j,vis[j]|=1;
    30         if(top&1) swap(num[2],num[top]),vis[num[top]]=0,--top;
    31         for(int j=1;j<=top;j+=2) tmp[++ans]=P(num[j],num[j+1]);
    32     } print(ans);
    33     for(int i=1;i<=ans;++i)
    34         print(tmp[i].first,' '),
    35         print(tmp[i].second);
    36     return Ot(),0;
    37 }
  • 相关阅读:
    Android开发 ViewConfiguration View的配置信息类
    Android 开发 倒计时功能 转载
    Android 开发 关于7.0 FileUriExposedException异常 详解
    Android 开发 实现文本搜索功能
    Android 开发 Activity里获取View的宽度和高度 转载
    Android 开发 存储目录的详解
    Android 开发 Fresco框架点击小图显示全屏大图实现 ZoomableDraweeView
    Android 开发 将window变暗
    Android 开发 DisplayMetrics获取Android设备的屏幕高宽与其他信息
    Android 开发 DP、PX、SP转换详解
  • 原文地址:https://www.cnblogs.com/Judge/p/9859989.html
Copyright © 2011-2022 走看看