zoukankan      html  css  js  c++  java
  • CodeForces

    先上题目

    k-Multiple Free Set

    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    A k-multiple free set is a set of integers where there is no pair of integers where one is equal to another integer multiplied by k. That is, there are no two integers x and y (x < y) from the set, such that y = x·k.

    You're given a set of n distinct positive integers. Your task is to find the size of it's largest k-multiple free subset.

    Input

    The first line of the input contains two integers n and k (1 ≤ n ≤ 105, 1 ≤ k ≤ 109). The next line contains a list of n distinct positive integers a1, a2, ..., an (1 ≤ ai ≤ 109).

    All the numbers in the lines are separated by single spaces.

    Output

    On the only line of the output print the size of the largest k-multiple free subset of {a1, a2, ..., an}.

    Sample test(s)
    Input
    6 2
    2 3 6 5 4 10
    Output
    3
    Note

    In the sample input one of the possible maximum 2-multiple free subsets is {4, 5, 6}.

      题意是给你一堆数,每个数只出现了一次,以及一个正整数倍数k,定义一种子集里面的x<y且x*k!=y,这种子集元素最多的时候个数有多大。

      这一题的分类暂时也不知道该分为什么,这种题好像曾经遇到过,可是当时好像也没有做出来,今天这一题感觉有点像是水过去的。

      做法是先对这些数进行排序,然后找出每一个数的k被在不在这些数里面,如果在,将那个数的位置记录下来,然后就从头开始扫描,遇到一个数,如果没有访问过,就访问它,看看的k倍,k*k倍,k*k*k倍···存不存在,并记录下最终从这个数按照访问它的这些倍数的个数,同时没访问完一个数,标记它已经被访问完,下次就不需要被访问了。

      那么为什么要这样做呢,解释如下:当一个数它不是某个数的k倍,同时它的k倍也不存在,那么在构成子集的时候,这个数就一定要选上;如果这个数是某个数的k倍,或者它的k倍在这些数里面的话,那它们的关系就可以用一条链来形容,因为每一个数至于它的k倍和它除以k的那个数有关,在这条链上面的其他数都与它没有关系,那我们只需要取这条链中相隔的数,就可以达到取最多数的目的。那么如果这条链的长度是偶数,那就去一半,如果是奇数,那就去平分后+1这么多的数目。

      这一题的数据量不大,可以开一个布尔数组标记某个值访问了没有,如果数据更加大,应该就要用set了。

      同时这一题的每一个数都只会出现一次,所以可以用这种方法贪心,如果是这个数出现不止一次的话,就不可以这样做了,那需要用dp。

    上代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 #define LL long long
     5 #define MAX (100000+10)
     6 using namespace std;
     7 
     8 
     9 typedef struct
    10 {
    11     LL d;
    12     int m;
    13 }S;
    14 
    15 S s[MAX];
    16 int c[MAX];
    17 bool f[MAX];
    18 
    19 bool cmp(S x,S y){return x.d<y.d;}
    20 
    21 int finds(int l,int r,LL t)
    22 {
    23     while(l<=r)
    24     {
    25         int mid=(l+r)>>1;
    26         if(s[mid].d<t) l=mid+1;
    27         else r=mid-1;
    28     }
    29     return l;
    30 }
    31 
    32 void deal(int t)
    33 {
    34     int i;
    35     c[t]=1;
    36     for(i=s[t].m;i!=-1;i=s[i].m)
    37     {
    38         c[t]++;
    39         f[i]=1;
    40     }
    41 }
    42 
    43 void check(int n)
    44 {
    45     int i;
    46     memset(c,0,sizeof(c));
    47     memset(f,0,sizeof(f));
    48     for(i=0;i<n;i++)
    49     {
    50         if(!f[i]) deal(i);
    51     }
    52 }
    53 
    54 int main()
    55 {
    56     int i,n;
    57     LL k,tot,M;
    58     //freopen("data.txt","r",stdin);
    59     scanf("%d %lld",&n,&k);
    60     M=-1;
    61     for(i=0;i<n;i++)
    62     {
    63         scanf("%lld",&s[i].d);
    64         M=s[i].d>M ? s[i].d : M;
    65     }
    66     sort(s,s+n,cmp);
    67     //s[n].d=M+2;
    68     //s[n].m=-1;
    69     for(i=0;i<n;i++)
    70     {
    71         LL t=s[i].d*k;
    72         s[i].m=finds(i+1,n,t);
    73         if(t!=s[s[i].m].d) s[i].m=-1;
    74     }
    75     check(n);
    76     tot=0;
    77     for(i=0;i<n;i++)
    78     {
    79         if(!f[i]) tot+=((c[i]+1)>>1);
    80     }
    81     printf("%lld",tot);
    82     return 0;
    83 }
    274A
  • 相关阅读:
    kill eclipse
    C语言之表达式运算整体提升
    查找函数对比:findall,search,match
    Linux backtrace()
    git本地协同
    git 撤销push到服务器的代码
    gtest
    C陷阱篇之enum默认长度
    程序员中文开发者手册
    C语言错题分析
  • 原文地址:https://www.cnblogs.com/sineatos/p/3231046.html
Copyright © 2011-2022 走看看