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
  • 相关阅读:
    173. Binary Search Tree Iterator
    199. Binary Tree Right Side View
    230. Kth Smallest Element in a BST
    236. Lowest Common Ancestor of a Binary Tree
    337. House Robber III
    449. Serialize and Deserialize BST
    508. Most Frequent Subtree Sum
    513. Find Bottom Left Tree Value
    129. Sum Root to Leaf Numbers
    652. Find Duplicate Subtrees
  • 原文地址:https://www.cnblogs.com/sineatos/p/3231046.html
Copyright © 2011-2022 走看看