• CF1497 E2. Squarefree division (hard version)


    Problem - E2 - Codeforces

    题意:

    有n个正整数,你至多可以把其中k个修改为任意的正整数

    你需要把这n个数划分为若干个连续的段,满足每一段的任意两个数的乘积都不是完全平方数

    问最少划分为多少段

    任意两个数的乘积都不是完全平方数

    等价于

    把区间内的数质因子分解,每个质因子的指数对2取模,任意两个数的结果都是不同的。

    因为可以修改为任意的正整数,所以相当于每个区间内质因子分解指数对2取模的结果至多有k个位置可以与区间内前面的数相同

    设dp[i][j]表示前i个数至多修改了j个位置的最少划分段数

    枚举最后一段修改了p个位置,假设这最后一段是区间[x,i],那么dp[i][j]可以用dp[x-1][j-p]+1更新

    就剩下x怎么求了

    预处理le[i][j]表示区间[L,i]至多修改j个数,满足要求的最小的L

    这个可以先枚举j,对于每个j用双指针的方法解决

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 200004
    
    int dp[N][21],le[N][21]; 
    int cnt[10000001];
    int a[N];
    
    int main()
    {
        int T,n,k,x,y,l;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;++i) 
            {
                scanf("%d",&a[i]);
                 x=1;
                for(int j=2;j*j<=a[i];++j)
                     if(!(a[i]%j))
                    {
                        y=0;
                        while(!(a[i]%j))
                        {
                            ++y;
                            a[i]/=j;
                        }
                        if(y&1) x*=j;
                     }
                 a[i]*=x;
            }
            for(int i=0;i<=k;++i)
            {
                x=0;
                l=1;
                for(int r=1;r<=n;++r)
                 {
                     cnt[a[r]]++;
                     if(cnt[a[r]]!=1) ++x;
                    while(x>i)
                    {
                        cnt[a[l]]--;
                        if(cnt[a[l]]) --x;
                        ++l; 
                    }
                    le[r][i]=l;
                 }
                while(l<=n) cnt[a[l++]]--;
            }
            for(int i=1;i<=n;++i)
                for(int j=0;j<=k;++j)
                    dp[i][j]=n;
            for(int i=1;i<=n;++i)
                for(int j=0;j<=k;++j)
                    for(int p=0;p<=j;++p)
                        dp[i][j]=min(dp[i][j],dp[le[i][p]-1][j-p]+1);
            printf("%d\n",dp[n][k]);
        }
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    程序员开发过程常见问题的解决方法(持续更新中....)
    android 单元测试
    浅谈android binder机制
    Android 写模块化代码注意事项
    Android View 简析
    PackageManager源码分析
    Android N做了啥
    JAVA HTTP POST参数为一个对象或数组
    Spring+Jetty+Jersey+Mybatis整合教程 无web.xml 、webapp版
    IKAnalyzer 添加扩展词库和自定义词
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15546141.html
Copyright © 2020-2023  润新知