牛客周赛Round 132(无F)

ICPC Time

思路:

模拟
代码:

cpp 复制代码
void solve()
{
    int n;
    cin>>n;
    if(n+5>=24)cout<<n+5-24;
    else cout<<n+5;
}

倍数

思路:

检查有没有 5 或者 0。
代码:

cpp 复制代码
void solve()
{
    string n;
    cin>>n;
    for(int i=0;i<n.size();i++){
        if(n[i]=='0'||n[i]=='5'){
            cout<<"YES"<<endl;
            return;
        }
    }
    cout<<"NO"<<endl;
}

邻合

思路:

动态规划,设 dp[i][0] 表示第 i 个数不修改的最小次数,dp[i][1] 表示第 i 个数修改的最小次数。

状态转移方程:
dp[i][0]=min(dp[i−1][0],dp[i−1][0]),gcd(a[i],a[i−1])≠1 dp[i][0]=min(dp[i-1][0],dp[i-1][0]),gcd(a[i],a[i-1])≠1 dp[i][0]=min(dp[i−1][0],dp[i−1][0]),gcd(a[i],a[i−1])=1
dp[i][1]=min(dp[i−1][0],dp[i−1][1])+1 dp[i][1]=min(dp[i-1][0],dp[i-1][1])+1 dp[i][1]=min(dp[i−1][0],dp[i−1][1])+1
dp[i][0]=dp[i−1][1] dp[i][0]=dp[i-1][1] dp[i][0]=dp[i−1][1]

还需要特判一下全为 1 的结果。注意这里的 if-else 结构如果当前位置 gcd 为 1 的话,如果当前位置不修改那么只能从上一位置修改转移过来。

🤔并没有验证方法的正确性😄,一步一步试出来的。
代码:

cpp 复制代码
const int N=2e5+5;
int a[N];
int dp[N][2];
void solve()
{
    int n;
    cin>>n;
    memset(dp,0x3f,sizeof dp);
    bool falg=true;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]!=1)falg=false;
    }
    if(falg){
        cout<<n<<endl;
        return;
    }
    int cnt=0;
    dp[1][0]=0;dp[1][1]=1;
    for(int i=2;i<=n;i++)
    {
        if(__gcd(a[i],a[i-1])!=1)dp[i][0]=min(dp[i-1][1],dp[i-1][0]);
        else dp[i][0]=dp[i-1][1];
        dp[i][1]=min(dp[i-1][0],dp[i-1][1])+1;
        
    }
    cout<<min(dp[n][1],dp[n][0])<<endl;
}

补充思路:

看到大神的简单题解了,写一下理解一下。a[i]=1a[i]=1a[i]=1 时是肯定要修改的。当 gcd(a[i],a[i−1])=1gcd(a[i],a[i-1])=1gcd(a[i],a[i−1])=1 时可以贪心将 a[i] 修改为 a[i+1]*a[i-1]。可以直接将这个数字设置成 0,这样之后计算 gcd 时会直接返回另一个数的值。
代码:

cpp 复制代码
void solve()
{
    int n;
    cin>>n;
    memset(dp,0x3f,sizeof dp);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(__gcd(a[i],a[i-1])==1)ans++,a[i]=0;
    }
    cout<<ans<<endl;
}

对和

思路:

模拟一下可以看出来,每个数字都会被计算 (n−1)(n-1)(n−1) 次,之后就是要处理下取整的问题,当和为奇数时就会进行下取整,即 (a+b−1)/2(a+b-1)/2(a+b−1)/2 的操作,那么统计有多少个奇数、偶数,然后进行组合一共有 i∗ji*ji∗j 组,然后计算。
代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
const int N=2e5+5;
int a[N];
void solve()
{
    int n;
    cin>>n;
    int sum=0;
    int cnt=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i]*(n-1);
        if(a[i]%2)cnt++;
    }
    int ans=sum-cnt*(n-cnt);
    cout<<ans/2<<endl;
}
signed main(){
	IOS
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
}

镜像

思路:

本质是最短路。

先来明确一下,只有个位不为 0 时才能反转,反转不会改变位数。

首先先来检测一下 a 是否比 b 大一位。如果大的话输出 -1

之后使用队列维护每一个遇到的值,使用 pair 来存储 {当前值,到达当前值的操作次数}。这样的话可能就会遍历很多,所以能剪枝的尽量剪。
代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define PII pair<int,int>
int a,b,k;
int rev(int x){
    int res=0;
    while(x>0){
        res=x%10+res*10;
        x/=10;
    }
    return res;
}
void solve()
{
    cin>>a>>b>>k;
    if(a==b){
        cout<<"0"<<endl;
        return;
    }
    queue<PII> q;
    q.push({a,0});
    int ans=-1;
    int mx=1;
    while(mx<b)mx*=10;
    if(a>=mx){
        cout<<"-1"<<endl;
        return;
    }
    vector<int> st(mx,0);
    st[a]=1;
    while(!q.empty()){
        auto [x,cnt]=q.front();
        q.pop();
        if(x%10){
            int r=rev(x);
            if(r==b){
                ans=cnt+1;
                break;
            }
            if(r<mx&&!st[r]){
                st[r]=1;
                q.push({r,cnt+1});
            }
        }
        int m=x+k;
        if(m==b){
            ans=cnt+1;
            break;
        }
        if(m<mx&&!st[m]){
            st[m]=1;
            q.push({m,cnt+1});
        }
    }
    cout<<ans<<endl;
}
signed main(){
	IOS
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
}
相关推荐
张李浩2 小时前
Leetcode 054螺旋矩阵 采用方向数组解决
算法·leetcode·矩阵
big_rabbit05022 小时前
[算法][力扣101]对称二叉树
数据结构·算法·leetcode
美好的事情能不能发生在我身上2 小时前
Hot100中的:贪心专题
java·数据结构·算法
2301_821700533 小时前
C++编译期多态实现
开发语言·c++·算法
xixihaha13243 小时前
C++与FPGA协同设计
开发语言·c++·算法
小小怪7503 小时前
C++中的函数式编程
开发语言·c++·算法
xixixiLucky4 小时前
编程入门算法题---小明爬楼梯求爬n层台阶一共多少种方法
算法
剑锋所指,所向披靡!4 小时前
数据结构之线性表
数据结构·算法
m0_672703316 小时前
上机练习第49天
数据结构·算法
样例过了就是过了6 小时前
LeetCode热题100 N 皇后
数据结构·c++·算法·leetcode·dfs·深度优先遍历