Codeforces Round #613 (Div. 2)

A

能到达的区间显然是连续的

n = int(input())
s = input()
l, r = s.count('L'), s.count('R')
print(l+r+1)

B

主角非选整个区间不可

中间的某一段 [ l , r ] [l,r] [l,r]的和等于 S − p r e f ( l − 1 ) − s u f ( r + 1 ) S - pref(l-1) - suf(r+1) Spref(l1)suf(r+1),要想它大于等于整个一端,就必须 p r e f ( l − 1 ) + s u f ( r + 1 ) ≤ 0 pref(l-1)+suf(r+1) \le 0 pref(l1)+suf(r+1)0,所以 p r e f ( l − 1 ) ≤ 0 pref(l-1) \le 0 pref(l1)0 s u f ( r + 1 ) ≤ 0 suf(r+1) \le 0 suf(r+1)0即可

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll n, a[maxn], pref[maxn], suf[maxn];
int main()
{
    ll T=read(), i, j, S, flag;
    while(T--)
    {
        n=read();
        rep(i,n)a[i]=read();
        rep(i,n)pref[i]=pref[i-1]+a[i];
        suf[n+1]=0;
        for(i=n;i;i--)suf[i]=suf[i+1]+a[i];
        flag=false;
        rep(i,n-1)if(pref[i]<=0 or suf[n-i+1]<=0)flag=true;
        if(flag)printf("NO\n");
        else printf("YES\n");
    }
    return 0;
}

C

答案肯定满足 ( a , b ) = 1 (a,b)=1 (a,b)=1,那么必定有 X = a b X=ab X=ab,枚举约数即可

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll x, i, j;
int main()
{
    ll ans=linf;
    x=read();
    for(i=1;i*i<=x;i++)
        if(x%i==0)
        {
            ll a=i, b=x/i;
            if(__gcd(a,b)==1)ans=min(ans,max(a,b));
        }
    printf("%lld %lld",ans,x/ans);
    return 0;
}

D

全部丢进字典树,然后从高位考虑

如果当前分叉既有 0 0 0又有 1 1 1,那么肯定最后答案里这一位是 1 1 1,但是 X X X的这一位应该填几呢?就 d p dp dp一下,看看往哪边走得到的最大值最小。

#include <bits/stdc++.h>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010*35
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct Trie
{
    int tot, ch[maxn][2], end[maxn];
    void init(){while(tot--)cl(ch[tot+1]),end[tot+1]=0;tot=1;}
    int* operator[](int index){return ch[index];}
    int id(char c){return c-0x30;}
    int append(int pos, int c)
    {
        int &t=ch[pos][c];
        return t?t:t=++tot;
    }
    int insert(char* s, int n)
    {
        int pos=1, i;
        for(i=1;i<=n;i++)pos=append(pos,id(s[i]));
        end[pos]++;
        return pos;
    }
}trie;
ll n, x, y, a[maxn], ans, f[maxn];
char s[50];
void dfs(int u, int j)
{
    auto x=trie[u][0], y=trie[u][1];
    if(x)dfs(x,j-1);
    if(y)dfs(y,j-1);
    if(x and y)
    {
        f[u]|=1ll<<j;
        f[u]|=min(f[x],f[y]);
    }
    else f[u]=f[x]+f[y];
}
int main()
{
    ll i, j;
    n=read();
    trie.init();
    rep(i,n)
    {
        ll t=read();
        for(j=0;j<30;j++)s[30-j]=!!( t&(1ll<<j) )+0x30;
        // cout<<s+1<<endl;
        trie.insert(s,30);
    }
    dfs(1,29);
    cout<<f[1];
    return 0;
}

E

把线段都按照左端点排序

考虑删去一段怎么求剩下的

假设第 1 1 1到第 i i i段都合并好了,第 i + 1 i+1 i+1段都合并好了,那么我记录左边有几段、右边有几段,再把左边的最大右端点记录下来,右边每条线段(合并过后)的左端点计下来,通过二分就可以知道左边“伸出”的这个右端点又覆盖了几个右边的左端点(假设这个数目是 c c c),两边的线段数相加,再减去 c c c,就是去掉第 i i i条线段的结果。左边的情况可以直接用经典方法的贪心来做,右边搞一个单调栈就行了。

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll v[maxn], n, T, ans[maxn], rt[maxn], cnt[maxn];
pll sg[maxn];
int main()
{
    T=read();
    ll i, j, l, b, t, o;
    while(T--)
    {
        n=read();
        rep(i,n)sg[i].first=read(), sg[i].second=read();
        sort(sg+1,sg+n+1);
        rt[0]=-linf;
        rep(i,n)
        {
            rt[i]=max(rt[i-1],sg[i].second);
            if(sg[i].first>rt[i-1])cnt[i]=cnt[i-1]+1;
            else cnt[i]=cnt[i-1];
        }
        t=n;
        v[n]=linf;
        ll now=0, mx=-1;
        for(i=n;i;i--)
        {
            
            auto c=upper_bound(v+t,v+n,rt[i-1])-(v+t);
            ans[i]=cnt[i-1]+now-c;
            mx=max(mx,ans[i]);
            now++;
            while(v[t]<=sg[i].second)t++, now--;
            v[--t]=sg[i].first;
        }
        printf("%lld\n",mx);
    }
    return 0;
}

F

这题好

先枚举 g c d gcd gcd,转换成找两个互质的数乘积最大

从大到小依次加入每个 x x x,假设当我加入 x x x的时候,之前存在一个 y y y x x x互质了,那么 x y xy xy就可以更新 a n s ans ans,并且 x x x y y y之间的数已经没有用了,只有比最大的 y y y还大的数还有用。

至于怎么确定有没有互质的,可以用容斥:
s = ∑ d ∣ x μ ( d ) c n t ( d ) s = \sum_{d|x} \mu(d) cnt(d) s=dxμ(d)cnt(d)
其中 c n t ( d ) cnt(d) cnt(d) d d d的倍数出现了多少次

如果 s > 0 s>0 s>0就说明还有和 x x x互质的数

具体实现我是用一个栈搞了搞,总之这题道理懂了就行了

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define maxe 100010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct EasyMath
{
    ll prime[maxn], phi[maxn], mu[maxn];
    bool mark[maxn];
    ll fastpow(ll a, ll b, ll c)
    {
        ll t(a%c), ans(1ll);
        for(;b;b>>=1,t=t*t%c)if(b&1)ans=ans*t%c;
        return ans;
    }
    void shai(ll N)
    {
        ll i, j;
        for(i=2;i<=N;i++)mark[i]=false;
        *prime=0;
        phi[1]=mu[1]=1;
        for(i=2;i<=N;i++)
        {
            if(!mark[i])prime[++*prime]=i, mu[i]=-1, phi[i]=i-1;
            for(j=1;j<=*prime and i*prime[j]<=N;j++)
            {
                mark[i*prime[j]]=true;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                mu[i*prime[j]]=-mu[i];
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
    }
    ll inv(ll x, ll p)  //p是素数
    {return fastpow(x%p,p-2,p);}
}em;
ll n, c[maxn], cnt[maxn];
vector<ll> factor[maxn];
ll calc(vector<ll> &v)
{
    ll n=v.size(), i, s, ans=-1, flag=false;
    stack<ll> stk;
    for(i=n-1;~i;i--)
    {
        s=0;
        for(auto d:factor[v[i]])s+=em.mu[d]*cnt[d];
        while(s)
        {
            ll x;
            do
            {
                x=stk.top(); stk.pop();
                for(auto d:factor[x])cnt[d]--, s-=em.mu[d]*(v[i]%d==0);
            }
            while( __gcd(v[i],x) > 1 );
            ans=max(ans,x*v[i]);
            flag=true;
        }
        if(!flag)
        {
            for(auto d:factor[v[i]])cnt[d]++;
            stk.push(v[i]);
        }
    }
    for(auto x:v)for(auto d:factor[x])cnt[d]=0;
    return ans;
}
int main()
{
    ll i, j, ans=-1;
    em.shai(1e5);
    n=read();
    rep(i,n)c[read()]++;
    for(i=1;i<maxn;i++)for(j=i;j<maxn;j+=i)factor[j].emb(i);
    for(i=1;i<maxn;i++)
    {
        vector<ll> v;
        for(j=i;j<maxn;j+=i)
        {
            auto t=c[j];
            if(j!=i)t=min(t,1ll);
            while(t--)v.emb(j/i);
        }
        ans=max(ans,calc(v)*i);
    }
    printf("%lld",ans);
    return 0;
}

评价

这套题数学成份比较多,是我喜欢的类型,做起来舒适极了。

那个 F F F还是蛮不错的

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值