题解:CF1992F Valuable Cards
Part 1:前言
题目翻译
在他最喜欢的咖啡馆里,Kmes再次想尝尝皮草大衣下的鲱鱼。以前,这对他来说并不难,但咖啡馆最近推出了一项新的购买政策。
现在,为了进行购买,Kmes需要解决以下问题:在他面前摆放着
Kmes被要求将这些卡划分为最少数量的坏段(这样每张卡只属于一个段)。如果无法选择乘积等于
从形式上讲,如果没有下标
帮助Kmes确定坏段的最小数量,以便享受他最喜欢的菜肴。
输入格式
第一行包含一个整数
每组输入数据的第一行分别给出整数
每组输入数据的第二行包含
保证所有测试数据集的
输出格式
对于每组输入数据,输出坏段的最小数量。
Part 2:思路
这道题,咱就选择贪心吧(主要是我 dp 不大会)。
坏段
显然,一个坏段的长度是有单调性的:当
所以,我们每次判断出一个段是坏段时,就把 ans 加一。
怎么判断呢?考虑用一个速度更快的 unordered_set,存储之前所有子序列的乘积。
每次循环遍历这个 unordered_set,令当前遍历到的为
但是这样时间复杂度太高,极端情况下,复杂度为
所以我们要考虑优化。
-
当
时,将 放入 unordered_set 里。 -
当
时,由于无论之后的数怎么样,子序列的乘积已经 了,就舍去。
Part 3:代码
你们终于来到了这里
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+5; ll t,n,x,a[N],ans; unordered_set<ll> st,us; inline void FIO(){ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl '\n' } inline void work(){ st.clear();us.clear();ans=1; cin>>n>>x; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++){ for(auto j:st){ ll k=a[i]*j; if(x%k==0){ if(k==x){ ans++;st.clear();us.clear(); break; } us.insert(k); } } for(auto j:us) st.insert(j); us.clear(); if(x%a[i]==0) st.insert(a[i]); } cout<<ans<<endl; } signed main(){ FIO(); cin>>t; while(t--) work(); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了