当前位置: 代码迷 >> 综合 >> Problem - 1475G - G. Strange Beauty(调和级数+dp)
  详细解决方案

Problem - 1475G - G. Strange Beauty(调和级数+dp)

热度:59   发布时间:2023-11-27 23:52:14.0

题目大意:对于一个序列,如果对于任意的 i , j ( i ≠ j ) i,j(i\neq j) i,j(i??=j)都满足 g c d ( a i , a i ) = m i n ( a i , a j ) gcd(a_i, a_i)=min(a_i,a_j) gcd(ai?,ai?)=min(ai?,aj?),那么就称该序列为有效序列.你现在可以删除给定序列中的一些元素,求最少删除多少元素,可以使得整个序列变为有效序列.

解题思路:我们首先考虑一下如何得到一个有效序列,枚举 a i a_i ai?进行因式分解,然后再对其分解后的因子再因式分解,这样复杂度很显然是不可行的,那我们正向思考一下,对于每个 a i a_i ai?,它所能产生的贡献一定是对应 k ? a i k*a_i k?ai?,枚举 a i a_i ai?,经过调和级数优化后复杂度就降到了 O ( n l o g n ) O(nlog_n) O(nlogn?).定义 d p [ i ] dp[i] dp[i]的含义是当前序列中最大数是 i i i时序列中的元素个数. d p [ i ? k ] = d p [ i ] + n u m [ i ? k ] dp[i*k]=dp[i]+num[i*k] dp[i?k]=dp[i]+num[i?k].

#include<bits/stdc++.h>
using namespace std;
int xxxxxxxx;
#define ll long long
#define syncfalse ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N = 2e5+5;
int num[N], dp[N];
void solve(){
    int n;cin>>n;int tem;int m =0 ;memset(num, 0, sizeof num);memset(dp, 0, sizeof dp);for (int i = 1; i <= n; ++i){
    cin>>tem;m=max(m, tem);num[tem]++;}for (int i = 1; i <= m; ++i){
    dp[i]=num[i];}for (int i = 1; i <= m; ++i){
    for (int j = 2; j * i <= m; ++j){
    dp[i*j]=max(dp[i*j], dp[i]+num[i*j]);}}int maxd = 0;for (int i = 1; i <= m; ++i)maxd=max(maxd, dp[i]);cout << n-maxd << "\n";
}int main(){
    syncfalse#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);#endifint t;cin>>t;for (;t;--t){
    solve();}return 0;
}
  相关解决方案