AtCoder Beginner Contest 161解题报告

题目链接

A. ABC Swap

题意:
给 三 个 数 , 交 换 a 和 b , 交 换 a 和 c 给三个数,交换a和b,交换a和c abac
题解:
签 到 题 , 直 接 用 s w a p 操 作 就 行 签到题,直接用swap操作就行 swap

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};



int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    int a,b,c;
    cin>>a>>b>>c;
    swap(a,b);
    swap(a,c);
    cout<<a<<' '<<b<<' '<<c<<endl;

    return 0;
}


B.Popular Vote

题意:
给 数 n 和 m , 和 一 个 长 度 为 n 的 数 组 a 给数n和m,和一个长度为n的数组a nmna
如 果 a i 大 于 等 于 数 组 a 的 s u m / ( 4 ∗ m ) 即 可 选 取 如果a_i大于等于数组a的sum/(4*m)即可选取 aiasum/(4m)
问 是 否 能 选 取 出 m 个 问是否能选取出m个 m
题解:
读 数 计 算 和 , 然 后 用 s u m 除 4 m 并 进 一 读数计算和,然后用sum除4m并进一 sum4m
由 于 a i 的 值 必 须 大 于 等 于 s u m , 而 且 a i 是 整 数 , 不 需 要 用 d o u b l e 的 方 法 就 是 进 一 由于a_i的值必须大于等于sum,而且a_i是整数,不需要用double的方法就是进一 aisumaidouble

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

int a[110];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    int n,m;
    cin>>n>>m;
    int sum=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    sum=(sum+4*m-1)/(4*m);
    int ans=0;
    for(int i=1;i<=n;i++){
        if(a[i]>=sum)ans++;
    }
    if(ans>=m)cout<<"Yes";
    else cout<<"No";
    return 0;
}


C.Replacing Integer

题意:
给 数 n 和 k , 每 次 n 变 成 n 和 k 的 差 的 绝 对 值 , 问 n 最 小 能 变 成 多 少 给数n和k,每次n变成n和k的差的绝对值,问n最小能变成多少 nknnkn
题解:
直 接 将 n 向 k 取 余 , 取 n 和 k − n 的 最 小 值 直接将n向k取余,取n和k-n的最小值 nknkn
由 于 n 和 k 都 是 < = 1 e 18 数 较 大 , 取 余 相 当 于 多 段 减 法 由于n和k都是<=1e18数较大,取余相当于多段减法 nk<=1e18
去 除 了 其 中 不 必 要 的 过 程 去除了其中不必要的过程
取 余 后 n 肯 定 小 于 k , 所 以 答 案 就 在 n 和 k − n 中 取 取余后n肯定小于k,所以答案就在n和k-n中取 nknkn

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

int a[110];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    ll n,k;
    cin>>n>>k;
    n%=k;
    cout<<min(n,k-n);

    return 0;
}


D.Lunlun Number

题意:
对 任 一 个 数 字 , 相 邻 两 位 差 的 绝 对 值 不 大 于 1 的 则 符 合 条 件 对任一个数字,相邻两位差的绝对值不大于1的则符合条件 1
问 从 小 到 大 第 k 个 符 合 条 件 的 问从小到大第k个符合条件的 k
题解
k < = 1 e 5 , 并 且 样 例 给 出 此 时 的 答 案 , 数 字 较 大 , 不 可 能 暴 力 查 数 k<=1e5,并且样例给出此时的答案,数字较大,不可能暴力查数 k<=1e5
所 以 每 次 直 接 找 符 合 的 数 , 最 多 找 1 e 5 次 所以每次直接找符合的数,最多找1e5次 1e5
这 里 采 用 B F S 对 数 位 进 行 查 找 , 每 次 查 最 后 一 位 的 相 邻 数 这里采用BFS对数位进行查找,每次查最后一位的相邻数 BFS
即 − 1 , 0 , + 1 的 情 况 , 特 判 一 下 0 和 9 少 其 中 一 种 情 况 即-1,0,+1的情况,特判一下0和9少其中一种情况 10+109

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    queue<ll> q;
    int n;
    cin>>n;
    int num=0;
    ll ans;
	for(int i=1;i<=9;i++) q.push(i);
	while(!q.empty()){
		ll p=q.front();
		q.pop();
        num++;
		if(num==n){ans=p;break;}
		int f=p%10;
		if(f==0){
			q.push(p*10);
			q.push(p*10+1);
		}
		else if(f==9){
            q.push(p*10+8);
            q.push(p*10+9);
		}
		else{
			q.push(p*10+f-1);
			q.push(p*10+f);
			q.push(p*10+f+1);
		}
	}
	cout<<ans;
    return 0;
}


E.Yutori

题意:
T a k a h a s h i 从 明 天 开 始 需 要 从 n 天 里 选 k 天 上 班 Takahashi从明天开始需要从n天里选k天上班 Takahashink
给 你 整 数 n , k , c , 和 一 个 字 符 串 s 给你整数n,k,c,和一个字符串s nkcs
要 符 合 以 下 两 个 条 件 T a k a h a s h i 才 去 上 班 要符合以下两个条件Takahashi才去上班 Takahashi
1. 距 离 上 次 上 班 已 经 过 了 c 天 1.距离上次上班已经过了c天 1.c
2. 第 i 天 的 s i 不 能 是 x 2.第i天的s_i不能是x 2.isix
问 哪 些 天 T a k a h a s h i 确 定 他 会 去 上 班 问哪些天Takahashi确定他会去上班 Takahashi
题解:
直 接 采 取 贪 心 策 略 直接采取贪心策略
倒 着 循 环 每 次 最 早 能 上 班 的 时 刻 上 班 , 然 后 找 c 天 后 的 不 是 x 的 天 倒着循环每次最早能上班的时刻上班,然后找c天后的不是x的天 cx
然 后 正 着 循 环 然后正着循环
这 两 个 分 别 是 T a k a h a s h i 上 班 的 左 区 间 和 右 区 间 这两个分别是Takahashi上班的左区间和右区间 Takahashi
只 要 这 个 区 间 最 后 聚 在 一 个 点 , 这 一 天 就 是 确 定 的 一 天 只要这个区间最后聚在一个点,这一天就是确定的一天

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

int l[maxn],r[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,k,c;
    cin>>n>>k>>c;
    string s;
    cin>>s;
    int cnt=k-1,mx=n;
    for(int i=s.length()-1;i>=0;i--)
        if(s[i]=='o'&&i<mx&&cnt>=0)r[cnt]=i,mx=i-c,cnt--;
    cnt=0,mx=-1;
    for(int i=0;i<s.length();i++)
        if(s[i]=='o'&&i>mx)l[cnt]=i,mx=i+c,cnt++;
    for(int i=0;i<k;i++)
        if(l[i]==r[i])cout<<l[i]+1<<endl;
    return 0;
}


F.Division or Substraction

题意:
给 一 个 数 n ( n < = 1 e 12 ) 给一个数n(n<=1e12) nn<=1e12
存 在 一 个 k , 如 果 n % k = = 0 , n = n / k 存在一个k,如果n\%k==0,n=n/k kn%k==0n=n/k
否 则 n = n − k 否则n=n-k n=nk
问 有 多 少 种 k 能 让 n 最 后 变 成 1 问有多少种k能让n最后变成1 kn1
题解:
由 于 n < = 1 e 12 所 以 可 以 推 测 是 用 根 号 方 法 ( 找 因 子 ) 由于n<=1e12所以可以推测是用根号方法(找因子) n<=1e12()
如 果 n % k ! = 0 , n 不 断 减 k 也 不 会 使 得 n 能 被 k 整 除 如果n\%k!=0,n不断减k也不会使得n能被k整除 n%k=0nk使nk
所 以 剩 下 的 操 作 只 有 多 段 减 法 , 就 可 以 转 换 成 取 余 所以剩下的操作只有多段减法,就可以转换成取余
所 以 先 找 能 让 n 不 能 整 除 , 但 是 取 余 后 直 接 等 于 1 的 所以先找能让n不能整除,但是取余后直接等于1的 n1
首 先 肯 定 是 n − 1 , n % ( n − 1 ) = 1 首先肯定是n-1,n\%(n-1)=1 n1n%(n1)=1
然 后 根 据 取 余 的 性 质 , n − 1 的 因 子 肯 定 也 可 以 符 合 然后根据取余的性质,n-1的因子肯定也可以符合 n1
找 完 直 接 取 余 等 于 1 的 之 后 , 就 找 能 整 除 的 找完直接取余等于1的之后,就找能整除的 1
然 后 找 n 的 因 子 直 接 先 除 到 不 能 整 除 再 取 余 模 拟 判 断 然后找n的因子直接先除到不能整除再取余模拟判断 n
最 后 答 案 加 上 自 身 最后答案加上自身
找 n 的 因 子 肯 定 是 2 − s q r t ( n ) 之 间 的 找n的因子肯定是2-sqrt(n)之间的 n2sqrtn
之 后 的 因 子 n 除 之 后 肯 定 比 他 本 身 小 , 就 不 能 进 行 下 一 步 操 作 之后的因子n除之后肯定比他本身小,就不能进行下一步操作 n

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ll n,t;
    cin>>n;
    int ans=0;
    for(ll i=1;i*i<=n-1;i++){
        if((n-1)%i==0){
            if(i!=1)ans++;
            if((n-1)/i!=i)ans++;
        }
    }

    for(ll i=2;i*i<=n;i++){
        if(n%i==0){
            t=n;
            while(t%i==0)t/=i;
            if(t%i==1)ans++;
        }
    }
    cout<<ans+1;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值