题意
有n张卡片,每张卡片有一个数字ai,其中不包括x。要求将卡片分为最小数量的分段,使得每个分段中任取几个数的成绩都不能是x,问最少要分几段。
思路
一个数如果不是x的因子,那么它与其他正整数相乘不会得到x。所以不考虑这种数
可以用set或map来存当前可以组成的乘积,将新加入的数字与集合中已有数字依次相乘(类似欧拉筛的思想)。需要注意的是 遍历集合进行相乘时不能将所得结果加入集合中导致再次相乘(赛时这一点没有处理好)
PS:map超时被hack了,改用undered_map可以过
代码
void solve() {
int n=read(),x=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
unordered_map<int,int>mp;
int ans=0;
for(int i=1;i<=n;i++){
if(x%a[i]==0){//x的因子才会对结果造成影响
if(mp[x/a[i]]>0){//乘积会构成x,分段
ans++;
mp.clear();
i--;
continue;
}else{
vector<int>res;//临时存放加入集合的元素
for (auto p : mp)
{
if(p.second==0)continue;
if(p.first*a[i]>x)continue;
res.push_back(p.first*a[i]);
}
mp[a[i]]++;
for(auto q:res){
mp[q]++;
}
res.clear();
}
}
}
cout<<ans+1<<endl;
}