蓝桥算法赛第6场

元宵节快乐

#include <iostream>
using namespace std;
int main()
{
    cout<<"Today AK!"<<'\n';
    return 0;
}

猜灯谜

#include <bits/stdc++.h>
using namespace std;
int arr[100010],n;
int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++) cin>>arr[i];
    for(int i=0;i<n;i++) {
        cout<<(arr[(i-1+n)%n]+arr[(i+1+n)%n])<<' ';
    }

    return 0;
}

数学奇才

不难发现对于一个长度为 n 的数组,在不超过 n 次操作下一定能将所有数变为正数,全部求和即可

#include <bits/stdc++.h>
using namespace std;
int arr[100010],n;
typedef long long ll;
int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    cin>>n;
    ll sum=0;
    for(int i=1;i<=n;i++) {
        cin>>arr[i];
        sum+=abs(arr[i]);
    }
    cout<<sum<<'\n';
    return 0;
}

你不干?有的是帕鲁干!

设一个任意奇数 x,则两个连续奇数的平方差可以表示为 x 2 − ( x − 2 ) 2 x^2-(x-2)^2 x2(x2)2,化简即可发现这个数一定是 8 的倍数,最后记得特判0的情况

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    int t;
    cin>>t;
    while(t--) {
        ll x;
        cin>>x;
        ll y=(x/4)+1;
        if(x%4==0&&y%2&&y-2>0) cout<<"Yes"<<'\n'<<(y-2)<<' '<<(y)<<'\n';
        else cout<<"No"<<'\n';
    }
    return 0;
}

等腰三角形

将两个数组排序之后,用双指针做,若 A ∗ 2 ≥ B A*2 ≥ B A2B 那么答案加一。

#include <bits/stdc++.h>
using namespace std;
int arr[200010],brr[200010];
int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>arr[i];
    for(int i=1;i<=n;i++) cin>>brr[i];
    sort(arr+1,arr+n+1),sort(brr+1,brr+n+1);
    int pa=n,pb=n,ans=0;
    while(pa&&pb) {
        if(arr[pa]*2>brr[pb]) {
            ans++,pa--,pb--;
        } else {
            pb--;
        }
    }
    cout<<ans<<'\n';
    return 0;
}

// 1 2 3 4
// 2 2 3 4

计算方程

计算 l o g k x log_kx logkx的方法:使用log函数,计算double res = log(x)/log(k),res 的值就是所求结果。
二分+库函数

#include <bits/stdc++.h>
using namespace std;
int k,m;
bool check(double x)
{
    return sqrt(x)+(int)(log(x)/log(k))-m>0;
}
int main()
{
    int t;
    cin>>t;
    while(t--) {
        cin>>k>>m;
        int l=1,r=1e9;
        while(l<r) {
            int mid=l+r>>1;
            if(check(mid)) r=mid;
            else l=mid+1;
        }
        cout<<r<<'\n';
    }
    return 0;
}

谁是帕鲁?

题目要求在给定区间中找出满足封闭图形个数等于 k 的数的数量,考虑用数位dp来解决。
在读入数据之前,我们提前初始化数组dp,使用dp[i][j]来表示一个 i 位的数字中封闭图形个数为 j 的方案数,由定义可以得到状态转移方程:dp[i][j] = dp[i - 1][j - number[1~9]],即 dp[i][j] 就等于当第 &j& 位数字为 u ( 1 ≤ u ≤ 9 ) u (1≤u≤9) u(1u9) 时,前 i − 1 i-1 i1 位数字中封闭图形个数为 j - number[u] 的方案数之和。
对于任意一个数字 x x x,我们可以将其表示为 A B C D E F . . . ABCDEF... ABCDEF...,那么假设数字 x x x A B C D E F ABCDEF ABCDEF,从最高位 A 开始向后遍历,在遍历过程中有以下两种情况:

  • 遍历最高位 A A A时:最高位不能为 0,所以应当从 1 开始枚举最高位 j ( 1 ≤ j ≤ A ) j(1≤ j ≤ A) j1jA,要求低位数的封闭图形个数为 k − n u m b e r [ j ] k-number[j] knumber[j].
  • 当不是最高位时,假设是 B B B,则 j ( 0 ≤ j ≤ B ) j(0≤j≤B) j0jB,则此时要求更低位数字封闭图形个数为 k − n u m b e r [ A ] − n u m b e r [ j ] k-number[A]-number[j] knumber[A]number[j].其次,我们还应当考虑数字仅有 5 位的情况(因为仅有5位数的数字大小一定小于6位数的 x)
    最后检查一下 x 本身的封闭图形个数是否为 k 个
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int number[]={1,0,0,0,1,0,1,0,2,1};
ll dp[15][25]; // 表示前i个数中封闭个数为j的种类数
ll l,r,k;
ll f(ll x)
{
    if(x==0) return 0ll;
    vector<int>num;
    while(x) num.push_back(x%10),x/=10;
    ll res=0,last=k,len=num.size();
    int self=0;
    for(int i=len-1;i>=0;i--) {
        self+=number[num[i]];
        for(int j=(i==(len-1));j<num[i];j++) {
            if(last>=number[j])
                res+=dp[i][last-number[j]];
        }
        if(i!=len-1) {
            for(int j=1;j<=9;j++) {
                if(k>=number[j])
                    res+=dp[i][k-number[j]];
            }
        }
        last-=number[num[i]];
    }

    res+=self==k;
    return res;
}
int main()
{
    dp[0][0]=1;
    for(int i=1;i<=12;i++)
        for(int j=0;j<=24;j++)
            for(int u=0;u<=9;u++)
                if(j>=number[u]) dp[i][j]+=dp[i-1][j-number[u]];
    cin>>l>>r>>k;
    cout<<(f(r)-f(l-1))<<'\n';
    return 0;
}

源石开采

通过线段树维护任意区间的最大值和次大值,求得sum。根据巴什博弈论,若sum能被m+1整除,则先手必败,否则先手必胜。
线段树某个节点的左节点最大值次大值分别为a、b,右节点为c、d,那么该节点的最大值为 m a x ( a , c ) max(a,c) max(a,c),次大值为 m a x ( m i n ( a , c ) , m a x ( b , d ) ) max(min(a,c),max(b,d)) max(min(a,c),max(b,d))

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int n,q,m,arr[200010];
struct node{
    int l,r,fir,sec;
}tr[200010*4];
void pushup(int u)
{
    tr[u].fir=max(tr[u<<1].fir,tr[u<<1|1].fir);
    tr[u].sec=max(min(tr[u<<1].fir,tr[u<<1|1].fir),max(tr[u<<1].sec,tr[u<<1|1].sec));
}
void build(int u,int l,int r)
{
    if(l==r)
        tr[u]={l,r,arr[r],0};
    else {
        int mid=l+r>>1;
        tr[u].l=l,tr[u].r=r;
        build(u<<1,l,mid),build(u<<1|1,mid+1,r);
        pushup(u);
    }
}
pii query(int u,int l,int r)
{
    if(tr[u].l>=l&&tr[u].r<=r) return {tr[u].fir,tr[u].sec};
    else {
        int mid=tr[u].l+tr[u].r>>1;
        pii a={0,0},b={0,0};
        if(l<=mid) a=query(u<<1,l,r);
        if(r>mid) b=query(u<<1|1,l,r);
        return {max(a.first,b.first),max(min(a.first,b.first),max(a.second,b.second))};
    }
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    cin>>n>>q;
    for(int i=1;i<=n;i++) cin>>arr[i];
    build(1,1,n);
    ll sum=0;
    while(q--) {
        int l,r;
        cin>>l>>r;
        auto res=query(1,l,r);
        // cout<<res.first<<' '<<res.second<<'\n';
        sum+=res.first+res.second;
    }
    cin>>m;
    cout<<sum<<'\n';
    cout<<(sum%(m+1)?"red":"blue")<<'\n';
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值