BZOJ4921「Lydsy1706月赛」互质序列

吐槽一下BZOJ没有C++11  题还是不难的

BZOJ 4921


题意

在长度为$ n$的数列中去掉非空的连续一段并保证剩下数字不少于$ 2$

求合法的所有方案中剩下数字的最大公约数的总和


$Solution$

记录一下前后缀$ gcd$

容易发现不同的$ gcd$的数量是$ log$级别的

为写起来方便用$ map$存即可


$ my \ code$

#include<bits/stdc++.h>
#define rt register int
#define ll long long
#define p 998244353
using namespace std;
int k,m,n,x,y,z,cnt,ans;
int qz[100010],hz[100010],a[100010];
map<int,int>s1,s2;
int main(){
    scanf("%d",&n);
    for(rt i=1;i<=n;i++)scanf("%d",&a[i]);
    qz[1]=a[1];for(rt i=2;i<=n;i++)qz[i]=__gcd(qz[i-1],a[i]);
    hz[n]=a[n];for(rt i=n-1;i>=1;i--)hz[i]=__gcd(hz[i+1],a[i]);
    ll ans=0;for(rt i=2;i<n;i++)ans+=qz[i]+hz[i];ans%=p;
    for(rt i=1;i<=n-2;i++)s1[qz[i]]++;
    for(rt i=n-2;i>=1;i--){
        s2[hz[i+2]]++;
        for(map<int,int>::iterator it=s2.begin();it!=s2.end();it++)
        (ans+=1ll*__gcd(qz[i],(*it).first)*(*it).second%p)%=p;
    }
    cout<<ans;
    return 0;
}

 

转载于:https://www.cnblogs.com/DreamlessDreams/p/10133336.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值