首页 > 其他分享 >Codeforces Round #846 (Div. 2)(B,E)

Codeforces Round #846 (Div. 2)(B,E)

时间:2023-02-07 00:33:05浏览次数:52  
标签:lfloor 846 frac gcd int sum Codeforces long Div

Codeforces Round #846 (Div. 2)(B,E)

B

B

题目大意是给一个长度为n的数组,我们可以把这个数组分成k段(k>1),我们有一个值是每一段的和的gcd

\(gcd(sum[1],sum[2]+...+sum[k])\),我们需要的是这个值的最大是多少

对于分成k段,假设此时的\(gcd\)为\(x\)

如果\(k=4\),那么\(sum[1]=x*cnt1 ,sum[2]=x*cnt2,sum[3]=x*cnt3,sum[4]=x*cnt4\),那么我们可以知道,这四个和都是\(x\)的倍数,并且要想\(x\)变得更大,那么我们考虑把后面的几个数合并,和还是\(x\)的倍数

对于\(gcd\),我们知道对于这些个不同的数(均是\(x\)的倍数)把某些数合并,才有可能可以让这些数的\(gcd\)变大

\(gcd=__gcd(sum[1],sum[2]+sum[3]+sum[4])\)

\(gcd=__gcd(sum[1]+sum[2],sum[3]+sum[4])\)

所以,我们可以想到,不管怎么分,只有分成两份的时候才有可能是那个最大的值

具体代码如下

#include <iostream>
#include <algorithm>
using namespace std;
#define int long long 
const int maxn=2e5+10;
#define int long long 
int a[maxn],sum[maxn];
int n,t;
void solve()
{
    cin>>n;
    sum[0]=0;
    int ans=0;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
        if (i==1) ans=a[i];
        else 
        {
            ans=__gcd(ans,a[i]);
        }
    }
    for (int i=1;i<n;i++)
    {
        ans=max(ans,__gcd(sum[i],sum[n]-sum[i]));
    }
    cout<<ans<<'\n';
    return ;
}
signed main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

D

交互题,不会

E

E

这个题通过分析后可以这么理解

输出一个\(L\)和\(R\),我们需要知道这一段之间的数的\(gcd\)有多少个不同的数

对于\(1\)到\(x\),我们可以通过

$ a=L,b=2*L,gcd(a,b)=L$

$ a=L+1,b=2*(L+1),gcd(a,b)=L+1$

$ a=L+2,b=2*(L+2),gcd(a,b)=L+2$

\(......\)

$ a=L+x,b=2*(L+x),gcd(a,b)=L+x,b=R$

那么对于\(gcd>=L\)的数有多少个呢

我们可以看到,有\(x+1\)个,\(cnt=x+1=\lfloor \frac{R}{2}\rfloor-L+1\)

那么对于\(gcd<L\)的,我们可以构造一个\(d\),其中一个数是\(d*\lceil \frac{L}{d}\rceil\),另外一个数是\(d*(\lceil \frac{L}{d}\rceil+1)\)

对于这个\(\lceil \frac{L}{d}\rceil\),我们可以发现可以有很多个\(d\),\(\lceil \frac{L}{d}\rceil\)都是一样的值,对于这些数,我们有一个范围,\([l,r]\)都是一个值

\(\lceil \frac{L}{l}\rceil\),所以,看到这儿是不是会想到整除分块了

什么是整除分块?

整除分块

通过这个我们有得到以下公式

\[\begin{cases} k=\lceil \frac{L}{i}\rceil =\frac{L+i-1}{i}=\lfloor \frac{L-1}{i}\rfloor+1\\ r=min(\lfloor \frac{R}{K+1}\rfloor,max(i)),\quad rk\leq L-1 \end{cases} \tag{1} \]

那么我们可以变化一下

\[\begin{cases} k=\lfloor \frac{L-1}{i}\rfloor\\ r=min(\lfloor \frac{R}{K+2}\rfloor,max(i)),\quad rk\leq L-1 \end{cases} \tag{1} \]

但是\(r\)的范围还要让\(r(k+1)<=r\),得到\(r=min(r,\lfloor \frac{R}{K+2}\rfloor)\)

#include <iostream>
#include <algorithm>
using namespace std;
#define int long long 
int L,R;
int t;
void solve()
{
    cin>>L>>R;
    int ans=max(0ll,R/2-L+1ll);
    int l=1,r=0;
    for (;l<L;l=r+1)
    {
        int k=(L-1)/l;
        r=(L-1)/k;
        int rr=min(r,R/(k+2));
        ans+=max(0ll,rr-l+1);
    }
    cout<<ans<<'\n';
    return ;
}
signed main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

标签:lfloor,846,frac,gcd,int,sum,Codeforces,long,Div
From: https://www.cnblogs.com/righting/p/17097094.html

相关文章