首页 > 其他分享 >CF1973F Maximum GCD Sum Queries 题解

CF1973F Maximum GCD Sum Queries 题解

时间:2024-05-24 23:07:19浏览次数:31  
标签:typedef ch GCD CF1973F 题解 cmb int read define

题目链接

点击打开链接

题目解法

首先想到枚举两个数列的 $\gcd $,求最小代价
两个数列的 \(\gcd\) 应该分别是 \(a_1,b_1\) 的因数 或 \(b_1,a_1\) 的因数
这样就把枚举范围缩小到了 \(d(a_1)\times d(b_1)\),这求最小代价需要 \(O(n)\),不够快

假设枚举的 \(\gcd\) 分别为 \(x,y\)
它可以产生合法解当且仅当:\(\forall i\in [2,n]\;(a_i\%x=0\) 且 \(b_i\%y=0)\) 或 \((a_i\%y=0\) 且 \(b_i\%x=0)\)
会产生 \(c_i\) 代价的数对 \((a_i,b_i)\) 需要满足:

  1. 不满足 \(a_i\%x=0\) 且 \(b_i\%y=0\)
  2. 满足 \(a_i\%y=0\) 且 \(b_i\%x=0\)

我们考虑一组 \((a_i,b_i)\) 对 \(x,y\) 的贡献,发现产生合法解和计算 \(c\) 都可以拆成若干数的因数加一个值
这可以做高维前缀和
后面的步骤就显然了

时间复杂度 \(O(d(V)d(V)\omega(V))\)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
template<typename T> void read(T &FF){
    FF=0;int RR=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    FF*=RR;
}
typedef vector<int> vi;
const int N=500010;
int n,q,a[N],b[N],c[N],id[N],ans[N];
LL qry[N];
vector<pii> cmb;
vi f;vector<LL> g;
int ind(int x,int y){ return lower_bound(cmb.begin(),cmb.end(),pair{x,y})-cmb.begin();}
vi get_div(int x){
    vi ret;
    for(int i=1;i*i<=x;i++) if(x%i==0){
        ret.pb(i);
        if(i!=x/i) ret.pb(x/i);
    }
    return ret;
}
vi get_pr(int x){
    vi ret;
    for(int i=2;i*i<=x;i++) if(x%i==0){
        ret.pb(i);
        while(x%i==0) x/=i;
    }
    if(x>1) ret.pb(x);
    return ret;
}
#define fi first
#define se second
typedef pair<LL,int> pli;
vector<pli> cost;
int main(){
    read(n),read(q);
    F(i,1,n) read(a[i]);
    F(i,1,n) read(b[i]);
    F(i,1,n) read(c[i]);
    F(i,1,q) read(qry[i]),id[i]=i;
    sort(id+1,id+q+1,[&](int x,int y){ return qry[x]<qry[y];});
    vi d1=get_div(a[1]),d2=get_div(b[1]);
    int tot=d1.size()*d2.size();
    f.resize(tot),g.resize(tot);
    F(o,0,1){
        cmb.clear();
        for(int x:d1) for(int y:d2) cmb.pb({x,y});
        sort(cmb.begin(),cmb.end());
        F(i,0,tot-1) f[i]=g[i]=0;
        F(i,2,n){
            int A1=gcd(a[1],a[i]),B1=gcd(b[1],b[i]);
            int A2=gcd(a[1],b[i]),B2=gcd(b[1],a[i]);
            f[ind(A1,B1)]++,f[ind(A2,B2)]++,f[ind(gcd(A1,A2),gcd(B1,B2))]--;
            g[ind(A2,B2)]+=c[i],g[ind(gcd(A1,A2),gcd(B1,B2))]-=c[i];
        }
        vi prm=get_pr(a[1]);
        for(int pr:prm){
            int j=tot-1;
            DF(i,tot-1,0) if(cmb[i].fi%pr==0){
                while(cmb[j]!=pair{cmb[i].fi/pr,cmb[i].se}) j--;
                f[j]+=f[i],g[j]+=g[i];
            }
        }
        prm=get_pr(b[1]);
        for(int pr:prm){
            int j=tot-1;
            DF(i,tot-1,0) if(cmb[i].se%pr==0){
                while(cmb[j]!=pair{cmb[i].fi,cmb[i].se/pr}) j--;
                f[j]+=f[i],g[j]+=g[i];
            }
        }
        F(i,0,tot-1) if(f[i]==n-1) cost.pb({g[i]+o*c[1],cmb[i].fi+cmb[i].se});
        swap(d1,d2),swap(a[1],b[1]);
    }
    sort(cost.begin(),cost.end());
    int val=0,curp=1;
    for(auto [c,v]:cost){
        while(curp<=q&&qry[id[curp]]<c) ans[id[curp]]=val,curp++;
        chkmax(val,v);
    }
    while(curp<=q) ans[id[curp]]=val,curp++;
    F(i,1,q) printf("%d ",ans[i]);puts("");
    return 0;
}

标签:typedef,ch,GCD,CF1973F,题解,cmb,int,read,define
From: https://www.cnblogs.com/Farmer-djx/p/18211816

相关文章

  • CF1909I Short Permutation Problem 题解
    这是一道*1900的黑。考虑枚举\(m\),将\(<\fracm2\)和\(\ge\fracm2\)的数分开讨论。考虑相邻两个数\(a,b\(a>b)\)分别在\(\fracm2\)的两侧,则有\(b\gem-a\)。考虑将所有数按某种方法从小到大排序,以\(\min(x,m-x)\)为第一关键字,\(-x\)为第二关键字,则排列中......
  • 【达梦问题解决】to_date转换之【文字与格式字符串不匹配】
    【问题描述】因为要转换的值中包含了不属于时间格式的字符(T,Z),这可能是数据迁移时时间参数设置不对导致的。具体没有进行考究【问题解决】使用DATE分隔符解决【手册链接】格式符解释实际分隔符的处理办法【自定义转换函数】这里的自定函数是不完善的,因为我的数......
  • NFLS NOI模拟 GCD
    涉及知识点:数位DP题意令\(\text{dig}(i)\)表示\(i\)十进制表示下各数位乘积,则一个数对是正确的当且仅当满足以下条件:\(1\leqi,j\leqn\)\(\text{dig}(i)\times\text{dig}(j)>0\)\(\gcd(\text{dig}(i),\text{dig}(j))\leqk\)给你\(n,k\(\leq10^{18})\)求......
  • CF1939D Big Persimmon 题解
    题目链接点击打开链接题目解法什么神仙题/jy先把\(a_i\)都\(\times2\),默认一开始先手比后手快\(1\)时间,可以避免两个人同时结束一个柿子的情况朴素的\(dp\)是显然的,令\(f_{l,r,det}\)表示当前剩下区间\([l,r]\)中的柿子,先手比后手快了\(det\)秒,先手最多能比后......
  • 充电桩——微信小程序,缴纳的1000元交易保障金,问题解答。
    1、小程序后台,申请退款保障金有一条不符合要求,无法退款。 2、咨询客服,能否退款然后再以公司名义缴纳保证金,等待回复:暂不支持对公转账,只能微信扫码支付缴纳哈。退保的话,支持退回对公账户。详情请查看小程序交易保证金管理规定https://developers.weixin.qq.com/miniprogram/de......
  • P5531 [CCO2019] Human Error 题解
    可能是一个比较劣的做法。但复杂度是对的。思路我们容易发现状态数非常的稀少。一个比较宽松的上限时\(3^{13}\)种状态由于每个点每走一步会吃掉一个棋子。所以实际的状态是远远达不到这个上限。那么我们可以直接设\(dp_{i,0/1,0/1}\)为在\(i\)状态下,目前是Justin......
  • Codeforces Global Round 12 C2. Errich-Tac-Toe (Hard Version) 题解 构造
    Errich-Tac-Toe(HardVersion)题目描述TheonlydifferencebetweentheeasyandhardversionsisthattokensoftypeOdonotappearintheinputoftheeasyversion.ErrichtogaveMonogonthefollowingchallengeinordertointimidatehimfromtakingh......
  • 蓝桥楼赛第30期-Python-第二天赛题 题解
    楼赛第30期Python模块大比拼解析网页元素目标本次挑战,我们需要使用Python访问软科世界大学排行榜来获取首页30所学校的信息。为避免目标网站的内容发生变化,我们使用保存之后的网页进行实验。链接如下:https://labfile.oss.aliyuncs.com/courses/4070/rank2021.h......
  • 优美子序列 题解
    有n个整数从左往右排成一行,构成一个序列a。如果通过删除原序列的若干个数(可以是删除0个),其他数保持位置不动,那么得到的序列就称为“子序列”。记sum表示序列a的所有数的总和,即sum=a[1]+a[2]+a[3]+...+a[n]。如果一个“子序列”的各个数加起来的和等于sum-1,那么这个“子序列”......
  • 题解:聪聪与可可(概率与期望)
    [NOI2005]聪聪与可可题目描述在一个魔法森林里,住着一只聪明的小猫聪聪和一只可爱的小老鼠可可。虽然灰姑娘非常喜欢她们俩,但是,聪聪终究是一只猫,而可可终究是一只老鼠,同样不变的是,聪聪成天想着要吃掉可可。一天,聪聪意外得到了一台非常有用的机器,据说是叫GPS,对可可能准确的定位......