首页 > 其他分享 >CF402D 题解

CF402D 题解

时间:2023-09-08 10:55:45浏览次数:33  
标签:gcd 从后 int 题解 CF402D res 我们 贪心

2023-09-04 18:42:46 solution

不难想到我们要先记录一下每一位的前缀 \(\gcd\),我们发现我们选择一位的前缀 \(\gcd\) 除掉以后,前缀 \(\gcd\) 会变为 \(1\) 并且会导致这位之后的 \(\gcd\) 全部为 \(1\)。所以每一位只能选择一次,并且我们从后往前扫肯定比从前往后扫要更优。

我们先把原序列原答案算出来,然后判断每一次除当前位的 \(\gcd\) 是否对答案有正贡献,贪心选择。这样为什么对呢?考虑我们第 \(i\) 位的贡献为正,但是我们不选,到 \(i-1\) 的时候,贡献可能变大,那显然我们后面除了对前面也没有影响,前面依然可以除剩下的,但是如果变小,说明前面不用除要让后面除。所以我们贪心从后往前选择是更优的。

如果我们直接贪心选了以后把前面的 \(\gcd\) 都除掉,发现复杂度是 \(O(n^2\sqrt{a})\) 的,这样肯定不行。注意到我们 \(\gcd\) 是单调不增的,所以我们从后往前是单调不减的,记录一下即可做到 \(O(n\sqrt{a})\),然而用线性筛跑了之后是远远跑不满的。

\(Code\)

int n,m,tot,prime[100005];
bool vis[100005];
ll ans,a[5002],b[5002];
unordered_set<ll>pd;
void init(){
    for(int i=2;i<=100000;i++){
        if(!vis[i])prime[++tot]=i;
        for(int j=1;j<=tot&&prime[j]*i<=100000;j++){
            vis[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}
ll cal(ll x){
    ll res=0;
    for(int i=1;prime[i]*prime[i]<=x;i++){
        if(x%prime[i])continue;
        ll cnt=0;
        while(x%prime[i]==0)x/=prime[i],cnt++;
        if(pd.find(prime[i])!=pd.end())res-=cnt;
        else res+=cnt;
    }
    if(x>1){
        if(pd.find(x)!=pd.end())res--;
        else res++;
    }
    return res;
}
int main(){
    n=read(),m=read();
    init();
    for(int i=1;i<=n;i++){
        a[i]=read();
        if(i==1)b[i]=a[i];
        else b[i]=__gcd(b[i-1],a[i]);
    }
    for(int i=1;i<=m;i++)pd.insert(read());
    for(int i=1;i<=n;i++)ans+=cal(a[i]);
    for(ll i=n,used=1,o;i;--i)
        if((b[i]/used>1)&&(o=cal(b[i]/used))<0)ans-=o*i,used=b[i];
    cout<<ans;
    return 0;
}

标签:gcd,从后,int,题解,CF402D,res,我们,贪心
From: https://www.cnblogs.com/NBest/p/17687004.html

相关文章

  • wzOI 2023.8.31 题解
    2023-09-0115:59:41$$前言$$太菜了,第一题都打成那样了没发现是MST,第三题数据范围没有很仔细看,以为是乱搞(组合之类的)题就直接跳了。不得不说这次比赛题目的一些思路还是挺妙的,一些想法确实我这种成分想不太到。$$A$$$$题意$$给出了\(m\)个可以查询的区间\([L_i,R_i]\)......
  • CF1103C 题解
    2023-09-0514:52:07solution找路径很好找,我们随便跑个dfs树找个深度\(\ge\frac{n}{k}\)的路径输出即可。可是怎么找\(k\)个长度不是\(3\)的倍数的环呢?既然我们跑了dfs树,那么就没有横叉边,对于叶子节点非树边只有返祖边,然后一看这个很奇怪的条件——保证每个点度数大......
  • CF1851 部分题解
    2023-07-3019:35:02前言因为我实在是太菜了,没时间也不会做最后两题,所以这里只有前\(5\)道签到题的题解。之后我有时间看了后两题的题解再来更新吧~A先不用看那么多七七八八的,搞清楚下面几点即可:高度不能相同。高度差得被整除。高度差不能太大。好了,然后就可以\(AC\)......
  • 暑假集训Day19 比赛题解
    2023-08-0516:22:13总结这次打下来,由于T2贪心不够完全,T3模拟\(5\)个时不是最优,T4想到暴力做法但是来不及打,加之全都是捆绑测试点,导致我T2,T3虽然加起来有不少点对了,但是还是判全错,最后也只剩下T1的100。感觉这次前三题也不难,都是可做的,T4的30pts暴力也很白给,但......
  • 暑假集训 Day17 模拟赛题解
    2023-08-0318:18:03前言好家伙,很少完整订正一场比赛,可能是因为这个比赛相对来说确实不难吧(至少正解不难)。总结与反思这场比赛其实没有我想象的那么难,只是觉得题目可能不简单,就没有往简单的思路想,反而是被之前讲过的题疑惑,以为要用到一些很奇特的算法,结果打完以后看了题解再结......
  • UVA10368 题解
    2023-08-0615:18:08solution双倍经验这种有限轮游戏的博弈通常都是有两种状态,必胜态和必败态。对于必胜态,指的是从它可以转移到必败态。对于必败态,指的是从它不论如何只能转移到必胜态。对于每个玩家都采取最优策略的有限游戏,我们通常只需要关注必胜态与必败态之间的转移即......
  • 【题解】AtCoder Regular Contest 162
    A.EkidenRace题目描述:有\(n\)个人参加了往返赛跑,每个人有一个编号\(1\)到\(n\)。已知以下信息:如果按照往路的成绩排序,那么任何两个人的成绩都不相同。同时第\(i\)个人在往路中排名第\(i\)。如果按照往返的成绩排序,那么任何两个人的成绩都不相同。同时第\(i\)个人......
  • P9189 [USACO23OPEN] Custodial Cleanup G 题解
    Description奶牛旅馆可以被看作一个\(N\)个节点\(M\)条边的无向简单图,其中每个房间有一个颜色\(C_i\),以及一个钥匙,颜色为\(S_i\),FJ最初在\(1\)号节点,手上一把钥匙都没有。FJ可以进行无数次以下操作:捡起当前房间的钥匙。(FJ可以同时手持多个钥匙)将部分或全部手......
  • All Pairs Maximum Flow题解
    前置知识:1.P3376【模板】网络最大流2.P4897【模板】最小割树(Gomory-HuTree)Ebola有一句很著名的话如果你乱搞过了我请你抽烟那么这道题肯定不能普通的dinic直接水过去,不然就不是紫题了,那么直接祭出最小割树,复杂度\(O(Tn^3m)\),但是因为dinic跑不满,所以是可以过的。......
  • [题解] AtCoder Beginner Contest 308 A~G
    AtCoderBeginnerContest308A~GA.NewSchemevoidMain(){vector<i64>a(8);for(auto&x:a)cin>>x;if(!is_sorted(a.begin(),a.end())&&!all_of(a.begin(),a.end(),[](auto&x){returnx%25!=0||!(100......