AtCoder Beginner Contest 161

传送门

A - ABC Swap

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    //freopen("in.txt","r",stdin);
    int a,b,c;
    scanf("%d%d%d",&a,&b,&c);
    printf("%d %d %d\n",c,a,b);
    return 0;
}
A.cpp

B - Popular Vote

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=105;
int a[N];
int main() {
    //freopen("in.txt","r",stdin);
    int n,m,sum=0;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) {
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    sort(a,a+n);
    int num=0;
    for(int i=n-1;i>=0;i--) {
        if(a[i]*4*m>=sum) num++;
        else break;
    }
    printf("%s\n",num>=m?"Yes":"No");
    return 0;
}
B.cpp

C - Replacing Integer

题意:给两个数N,K,每次操作可以将N变为abs(N-K),求若干次操作后N最小可能的值。

数据范围:$0 \leq N \leq 10^{18}, 1 \leq K \leq 10^{18}$

题解:当N大于等于K的时候,N要一直减K,等价于N%K,取模完只需要取min(N,K-N)即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    //freopen("in.txt","r",stdin);
    ll n,k;
    scanf("%lld%lld",&n,&k);
    n%=k;
    printf("%lld\n",min(n,k-n));
    return 0;
}
C.cpp

D - Lunlun Number

题意:将十进制下不包含前导零,且相邻两位的数字差不超过1的数称为lunlun数,求第K大的lunlun数。

数据范围:$1 \leq K \leq 10^{5}$

题解:二分答案,通过数位dp求1~x的lunlun数。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[70],cnt;
ll f[70][10][2];
ll dfs(int pos,int la,bool limit,bool pre) {
    if(pos==0) return pre?1:0;
    if(f[pos][la][pre]!=-1&&!limit) return f[pos][la][pre];
    int up=limit?a[pos]:9;
    ll ans=0;
    for(int i=0;i<=up;i++) {
        if(pre&&abs(i-la)>=2) continue;
        ans+=dfs(pos-1,i,i==up&&limit,pre|i);
    }
    if(!limit) f[pos][la][pre]=ans;
    return ans;
}
ll cal(ll x) {
    cnt=0;
    while(x)
        a[++cnt]=x%10,x/=10;
    ll ans=0;
    if(cnt>1) ans+=dfs(cnt-1,0,false,false);
    for(int i=1;i<=a[cnt];i++)
        ans+=dfs(cnt-1,i,i==a[cnt],true);
    return ans;
}
int main() {
    //freopen("in.txt","r",stdin);
    memset(f,-1,sizeof f);
    int x;
    scanf("%d",&x);
    ll L=1,R=3234566667,ans;
    while(L<=R) {
        ll mid=(L+R)>>1;
        if(cal(mid)>=x) ans=mid,R=mid-1;
        else L=mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}
D.cpp

 E - Yutori

题意:在N天中选择K天工作,给一个长度为N的字符串,其中'x'代表这天休息,'o'表示这天可以工作,每工作一天后接下来C天不工作,求哪些天是必须工作的。

数据范围:$1 \leq K \leq N \leq 2 \times 10^{5},0 \leq C \leq N$

题解:从前开始贪心选择最前面的满足要求的K天,第x次工作记为L[x],那么所有第x次工作的可能时间肯定在第L[x]天及之后,然后反正来一遍求出R[x],要是L[x]=R[x],那么第x次工作只能在第L[x]天。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5;
char s[N];
vector<int> L,R;
int main() {
    //freopen("in.txt","r",stdin);
    int n,k,c;
    scanf("%d%d%d%s",&n,&k,&c,s+1);
    for(int i=1;i<=n;) {
        if(s[i]=='o') L.push_back(i),i+=c;
        i++;
        if(L.size()==k) break;
    }
    for(int i=n;i>=1;) {
        if(s[i]=='o') R.push_back(i),i-=c;
        i--;
        if(R.size()==k) break;
    }
    for(int i=0;i<k;i++) {
        if(L[i]==R[k-i-1]) printf("%d\n",L[i]);
    }
    return 0;
}
E.cpp

F - Division or Substraction

题意:给一个正整数N,对于K=2,3,...,N,每次操作如果K|N,那么N=N/K,反之,N=N-K,直到N小于K,求有多少个K让N最终变为1。

数据范围:$2\leq N \leq 10^{12}$

题解:1.当N%K!=0时,由于N%K!=0,那么(N-K)%K!=0,所以最后N变成N%K,现在要求多少个K使得N%K=1,就是n-1的所有约数(不包括1)。

2.当N%K==0时,那么N一直除以K,直到不能除为止,此时N%K!=0,只需要判断N%K是否为1即可。可以发现:当$a \times b =N(2 \leq a\leq b)$,K只取a才可能有解,最后把N=K这种情况加上。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll cal(ll k,ll n) {
    if(n<k) return n;
    if(n%k==0) return cal(k,n/k);
    return n%k;
}
int main() {
    //freopen("in.txt","r",stdin);
    ll n,m,ans=0;
    scanf("%lld",&n),m=n-1;
    for(ll i=1;i*i<=m;i++) {
        if(m%i==0) {
            ans++;
            if(i*i!=m) ans++;
        }
    }
    for(ll i=2;i*i<=n;i++) {
        if(n%i==0) {
            ans+=(cal(i,n)==1);
        }
    }
    printf("%lld\n",ans);
    return 0;
}
F.cpp

 

posted @ 2020-04-05 12:05  zdragon  阅读(302)  评论(0编辑  收藏  举报