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; }
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; }
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; }
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; }
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; }
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; }