牛客周赛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();
	}
}
相关推荐
Lee川1 小时前
深入解析:从内存模型到作用域陷阱——JavaScript变量的前世今生
javascript·算法
㓗冽2 小时前
回文数2(字符串)-基础题97th + 加法器(字符串)-基础题98th + 构造序列(字符串)-基础题99th
算法
陈天伟教授2 小时前
人工智能应用- 预测化学反应:02. 化学反应简介
人工智能·神经网络·算法·机器学习·推荐算法
plus4s3 小时前
2月23日(97-99题)
算法
hansang_IR3 小时前
【记录】AT_abc406模拟赛
c++·算法·模拟赛
blackicexs3 小时前
第六周第一天
数据结构·算法
52Hz1183 小时前
力扣20.有效的括号、155.最小栈
python·算法·leetcode
菜鸡儿齐4 小时前
leetcode-电话号码的字母组合
算法·leetcode·职场和发展
We་ct4 小时前
LeetCode 236. 二叉树的最近公共祖先:两种解法详解(递归+迭代)
前端·数据结构·算法·leetcode·typescript