Divisibility HDU - 3335

Posted mzchuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Divisibility HDU - 3335相关的知识,希望对你有一定的参考价值。

As we know,the fzu AekdyCoin is famous of math,especially in the field of number theory.So,many people call him "the descendant of Chen Jingrun",which brings him a good reputation.
AekdyCoin also plays an important role in the ACM_DIY group,many people always ask him questions about number theory.One day,all members urged him to conduct a lesson in the group.The rookie daizhenyang is extremely weak at math,so he is delighted. 
However,when AekdyCoin tells us "As we know, some numbers have interesting property. For example, any even number has the property that could be divided by 2.",daizhenyang got confused,for he don‘t have the concept of divisibility.He asks other people for help,first,he randomizely writes some positive integer numbers,then you have to pick some numbers from the group,the only constraint is that if you choose number a,you can‘t choose a number divides a or a number divided by a.(to illustrate the concept of divisibility),and you have to choose as many numbers as you can. 
Poor daizhenyang does well in neither math nor programming.The responsibility comes to you!

InputAn integer t,indicating the number of testcases, 
For every case, first a number n indicating daizhenyang has writen n numbers(n<=1000),then n numbers,all in the range of (1...2^63-1). 
OutputThe most number you can choose.Sample Input

1
3
1 2 3 

Sample Output

2


Hint:
If we choose 2 and 3,one is not divisible by the other,which is the most number you can choose.

题意:给定一组数,要求数中选取互不为约束的数,问最多选取多少个;

思路:
虽然这个题目让我们求得是最大值,其实是在最小值里面的最大值,DLX可重复覆盖的模板是为了找到最小值,所以找到最小值的过程中默认了选择某一个之后和他相关连的都不用在选择了。。。
而这样正好就符合了这个题目的要求,构造的话就是n行n列就好,代表这n个数,将与此数有约数关系的数取值为1.当选中一列时,与此列中的数有约数关系的数
都将删去。另外加一点剪枝使代码更高效。

代码:
  1 #include <cstdio>
  2 #include <fstream>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <deque>
  6 #include <vector>
  7 #include <queue>
  8 #include <string>
  9 #include <cstring>
 10 #include <map>
 11 #include <stack>
 12 #include <set>
 13 #include <sstream>
 14 #include <iostream>
 15 #define mod 1000000007
 16 #define eps 1e-6
 17 #define ll long long
 18 #define INF 0x3f3f3f3f
 19 using namespace std;
 20 
 21 const int maxn=1010*1010;
 22 struct DLX
 23 
 24     int left[maxn],right[maxn],up[maxn],down[maxn],col[maxn];
 25     int head[maxn],num[1010];
 26     int ansed,id;
 27     void init(int nn)
 28     
 29         int n=nn;
 30         for(int i=0;i<=n;i++)
 31         
 32             left[i]=i-1;
 33             right[i]=i+1;
 34             up[i]=down[i]=i;
 35             col[i]=i;
 36         
 37         left[0]=n;
 38         right[n]=0;
 39         ansed=0;
 40         id=n;
 41         memset(num,0,sizeof(num));
 42         memset(head,-1,sizeof(head));
 43     
 44     void link(int x,int y)
 45     
 46         id++;
 47         up[id]=up[y];
 48         down[id]=y;
 49         down[up[y]]=id;
 50         up[y]=id;
 51         num[y]++;
 52         col[id]=y;
 53         if(head[x]==-1)
 54         
 55             head[x]=left[id]=right[id]=id;
 56         
 57         else
 58         
 59             left[id]=left[head[x]];
 60             right[id]=head[x];
 61             right[left[head[x]]]=id;
 62             left[head[x]]=id;
 63         
 64     
 65     void remove(int c)//移除列
 66     
 67         for(int i=down[c];i!=c;i=down[i])
 68         
 69             left[right[i]]=left[i];
 70             right[left[i]]=right[i];
 71         
 72     
 73     void reback(int c)//恢复列
 74     
 75         for(int i=up[c];i!=c;i=up[i])
 76         
 77             left[right[i]]=i;
 78             right[left[i]]=i;
 79         
 80     
 81     int A()//未剪掉的列
 82     
 83         int s=0;
 84         for(int i=right[0];i!=0;i=right[i])
 85         
 86             s++;
 87         
 88         return s;
 89     
 90     void danc(int step)
 91     
 92         if(right[0]==0)
 93         
 94             if(step>ansed)//解中的最大值
 95             
 96                 ansed=step;
 97             
 98             return ;
 99         
100         if(A()+step<=ansed)//如果剩下的步骤与已走的步骤比当前答案少,则停止循环
101         
102             return ;
103         
104         int c=right[0];
105         for(int i=c;i!=0;i=right[i])//优先处理列中数字少的
106         
107             if(num[i]<num[c])
108             
109                 c=i;
110             
111         
112         for(int i=down[c];i!=c;i=down[i])
113         
114             remove(i);
115             for(int j=right[i];j!=i;j=right[j])
116             
117                 remove(j);
118             
119             danc(step+1);
120             for(int j=left[i];j!=i;j=left[j])
121             
122                 reback(j);
123             
124             reback(i);
125         
126     
127 dlx;
128 int main()
129 
130     int t;
131     scanf("%d",&t);
132     while(t--)
133     
134         ll num[1010];
135         int n;
136         scanf("%d",&n);
137         dlx.init(n);
138         for(int i=0;i<n;i++)
139         
140             scanf("%lld",&num[i]);
141         
142         for(int i=0;i<n;i++)
143         
144             for(int j=0;j<n;j++)
145             
146                 if(num[i]%num[j]==0||num[j]%num[i]==0)
147                 
148                     dlx.link(i+1,j+1);
149                 
150             
151         
152         dlx.danc(0);
153         printf("%d\n",dlx.ansed);
154     
155 

 

以上是关于Divisibility HDU - 3335的主要内容,如果未能解决你的问题,请参考以下文章

HDU3335 Divisibility Dilworth定理+最小路径覆盖

POJ3335(半平面交)

[模拟赛] Divisibility 数论

百练1745:Divisibility

Codeforces 922F Divisibility 构造

18.06.30 POJ 百练1745:Divisibility