题目描述 Description
有这样的一个集合,集合中的元素个数由给定的N决定,集合的元素为N个不同的正整数,一旦集合中的两个数x,y满足y = P*x,那么就认为x,y这两个数是互斥的,现在想知道给定的一个集合的最大子集满足两两之间不互斥。
输入有多组数据,每组第一行给定两个数N和P(1<=N<=10^5, 1<=P<=10^9)。接下来一行包含N个不同正整数ai(1<=ai<=10^9)。
输出一行表示最大的满足要求的子集的元素个数。
4 2
1 2 3 4
3
Codevs1230 元素查找
题目描述 Description
给出n个正整数,然后有m个询问,每个询问一个整数,询问该整数是否在n个正整数中出现过。
第一行两个整数 n 和m。
第二行n个正整数(1<=n<= 100000)
第三行m个整数(1<=m<=100000)
一共m行,若出现则输出YES,否则输出NO
4 2
2 1 3 4
1 9
YES
NO
所有数据都不超过10^8
对于这两个题,由于难度比较低,所以使用最简单的哈希函数取模运算就好了
然后用开放域法将其存储。
当然我们有更加高端的存储方法和解决冲突的方法,不过由于个人太弱而/不会使用指针,完全不会用QAQ
其实个人更加偏向使用多个HASH函数解决冲突,但是还不太会用orz
史上第一次HASH的练习
愉快的贴代码时刻www
1553
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,p,a[100001],ans;
int pd[1000008];
void hash(int x)
{
int t=x;
while (t%p==0)
t/=p;
t=t%1000007;
while(1)
{
if(!pd[t])
{
pd[t]=x;
ans++;
return;
}
else
{
if (x%pd[t]==0)
{
if (x/pd[t]!=p)
{
ans++;
pd[t]=x;
}
return;
}
else
{
t++;
if(t==1000008) t=0;
}
}
}
}
main()
{
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
hash(a[i]);//哈希函数(最朴素版本)
printf("%d",ans);
}
1230 元素查找//P.S.本题除了hash其实有更快更简单的解法。比如直接价加个布尔数组暴力什么的事实证明hash效率比那样要低很多
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,hs[100007];
bool pd[100007];
int hash(int x)
{
int t=x%100007;
while(pd[t]&&hs[t]!=x)
t=(t+1)%100007;
pd[t]=1;
return t;
}
int main(){
memset(pd,0,sizeof(pd));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
hs[hash(t)]=t;
}
for(int i=1;i<=m;i++)
{
int t;
scanf("%d",&t);
if(hs[hash(t)]==t) printf("YES\n");
else printf("NO\n");
}
return 0;
}