AtCoder Beginner Contest 161题解

终于写全了
贴一波博客园的地址:传送门html

A ABC Swap

题意:依次交换AB,AC中的元素,输出最后结果
若是实在懒得想就像我同样看着题写两个swapios

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
#define db double
#define ld long double
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#pragma GCC optimize(2)
#define ull unsigned long long
#define maxn 1020
signed main()
{
    IOS
    int x,y,z;
    cin>>x>>y>>z;
    swap(x,y);
    swap(x,z);
    cout<<x<<" "<<y<<" "<<z;
    return 0 ;
}

B Popular Vote

题意:N个物品,每一个都有一个权值,询问是否存在M个物品,其中每一个物品的权值不小于权值和的 1 4 M \frac{1}{4M}
先算出总和,而后O(N)遍历,一个简单的移项能够帮助你避免浮点数的使用c++

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
#define db double
#define ld long double
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#pragma GCC optimize(2)
#define ull unsigned long long
#define maxn 110
ll lcm(ll a,ll b){return a*b/__gcd(a,b);}
void dfs(){}
int a[maxn];
signed main()
{
    IOS
    int n,m;
    ll sum=0;
    cin>>n>>m;
    for (int i = 0; i <n ; ++i) {
        cin>>a[i];
        sum+=a[i];
    }
    int cnt=0;
    for (int j = 0; j <n ; ++j) {
        if(a[j]*4*m>=sum)cnt++;
    }
    if(cnt>=m)cout<<"Yes";
    else cout<<"No";
    return 0 ;
}

C Replacing Integer

题意:给你N和K,每次能够把N替换为N和K差的绝对值,询问全部替换中N的最小值
很简单的一道思惟题,若是N大于K,那么N就能够写成M*K+b的形式,而若是N小于等于K,N会在N和K-N之间反复横跳,那么咱们只须要去找N%K和K-N%K之中的最小值便可web

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
#define db double
#define ld long double
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#pragma GCC optimize(2)
#define ull unsigned long long
#define maxn 110
int a[maxn];
ll n,k;
signed main()
{
    IOS
    cin>>n>>k;
    if(n%k==0)cout<<0;
    else{
        n%=k;
        cout<<min(n,k-n);
    }
    return 0 ;
}

D Lunlun Number

题意:lunlun数的定义是该数字每一位与相邻位差的绝对值小于等于1,求第k小的lunlun数
二维dp,一开始想的打表,但实在太懒,就去搞dp了,而范围也不用太大,差很少10*10的二维数组,dp[i][j]表示当前数字有i位,而后首位数字为j的方案数,而后转移的时候就很好转移了,只须要在dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1]三者里找到合法的项加上便可。求出来以后怎么办呢,依次遍历每一项,若是K小于等于当前的dp值,那么要找的数必定在这个状态里,不然K-当前的dp值,继续遍历。
当咱们找到dp[i][j]>=K的状况时,只须要在i-1的状况里继续找便可,只不过每次第二维被限制在j-1,j,j+1,当第一维为0时输出便可。数组

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
#define db double
#define ld long double
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#pragma GCC optimize(2)
#define ull unsigned long long
#define maxn 110
int dp[maxn][maxn];
signed main()
{
    IOS
    int num;
    cin>>num;
    memset(dp,0, sizeof(dp));
    for (int k = 0; k <=9 ; ++k) {
        dp[1][k]=1;
    }
    for (int i = 2; i <=10 ; ++i) {
        for (int j = 0; j <=9 ; ++j) {
            dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+dp[i-1][j+1];
        }
    }
    queue<int> ans;
    int l=0, r = 0,fl=0;
    for (int j = 1; j <=10 ; ++j) {
        for (int i = 1; i <=9 ; ++i) {
            if(num<=dp[j][i]){
                l=j;
                r=i;
                fl=1;
                break;
            }
            num-=dp[j][i];
        }
        if(fl==1)break;
    }
    l--;
    ans.push(r);
    while(l!=0){
        if(num<=dp[l][r-1]){
            r--;
            ans.push(r);
        }else{
            num-=dp[l][r-1];
            if(num<=dp[l][r]){
                ans.push(r);
            }else{
                num-=dp[l][r];
                r++;
                ans.push(r);
            }
        }
        l--;
    }
    while(!ans.empty()){
        int now=ans.front();
        cout<<now;
        ans.pop();
    }
    return 0 ;
}

E Yutori

题意:Takahashi须要选择K天工做,若是某一天他工做了,那么以后C天都不用工做,同时存在一些日子,这些日子里他不用工做,询问在全部的挑选方案里,哪一天必须工做?
这道题比赛没切出来(我是屑 ),看完大佬代码以后,发现是一道贪心水题,咱们先记录Takahashi最勤快的状况(尽可能早地完成工做)是哪几天,最懒惰的状况(与前者相反)是哪几天,而后去找交集,若是某个元素在两者中都出现且位次一致,那么这天就是必须工做的。
为何贪心是对的呢?
这里说一说本蒟蒻的思路:
首先若是某一天必须工做,那么它必定出如今最勤快和最懒惰的状况,那么交集是确定正确的。那么位次不一样为何就不合法呢?咱们假设最勤快的状况是一、三、5,最懒惰的状况是三、五、7,交集是三、5,可是咱们能够取一、五、7(不取3),也能够取一、三、7(不取5),显然只有交集中位次相同的才是对的。app

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
#define db double
#define ld long double
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#pragma GCC optimize(2)
#define ull unsigned long long
#define maxn 200005
int l[maxn],r[maxn];
signed main()
{
    IOS
    int n,k,c;
    string s;
    cin>>n>>k>>c;
    cin>>s;
    int cnt=0;
    memset(l,-1, sizeof(l));
    memset(r,-1, sizeof(r));
    for (int i = 0; i <n&&cnt<k ; ++i) {
        if(s[i]=='x')continue;
        else{
            l[cnt++]=i;
            i+=c;
        }
    }
    cnt=k-1;
    for (int j = n-1; j >=0&&cnt>=0 ; --j) {
        if(s[j]=='x')continue;
        else{
            r[cnt--]=j;
            j-=c;
        }
    }
    for (int m = 0; m <k ; ++m) {
        if(l[m]==r[m]&&l[m]!=-1)cout<<l[m]+1<<endl;
    }
    return 0 ;
}

F Division or Substraction

题意:在2~N之间选一个数,而后进行下列操做:ide

  • 若是N模K等于0,将N替换为N/K
  • 若是N模K不为0,将N替换为N-K

求能够使N变成1的K的取值方案数svg

数论水题啦,一开始的思路分的状况有点多,听了学长的思路发现部分方案能够合并,以下:
很容易能够想到一种合法的状况是一直除到1,还有一种状况是先除再减,即对每个合法的k,我么均可以把n写成下面的形式 k p ( a k + 1 ) {k^p}*{(a*k+1)} 其中p>=0,a>=0而且两者不一样时为0(1不合法),那么只须要分别讨论p为0和不为0的状况就好,为0几乎就是求n-1的因子数了, N \sqrt{N} 的时间能够解出来,另外一种状况其实也能够在相同的时间复杂度内解出来,由于p不为0时,只有a=0时,式子中才不会出现 k 2 {k^2} ,容易解出大于 N \sqrt{N} 的范围内只有N时知足题意的,只须要枚举2~ N \sqrt{N} 便可。
(合并方案后用时居然从四位数快到了两位数)spa

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
#define db double
#define ld long double
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#pragma GCC optimize(2)
#define ull unsigned long long
#define maxn 110
signed main()
{
    IOS
    ll n;
    cin>>n;
    ll ans=1;
    for (ll i = 2; i <=(ll)sqrt(n) ; ++i) {
        ll now=n;
        while(now%i==0){
            now/=i;
            if((now-1)%i==0){
                ans++;
                break;
            }
        }
    }
    n--;
    for (ll l = 1; l <=(ll)sqrt(n) ; ++l) {
        if(n%l==0){
            ans+=2;
            if(l==1)ans--;
            if(l*l==n)ans--;
        }
    }
    cout<<ans;
    return 0 ;
}