码迷,mamicode.com
首页 > 其他好文 > 详细

AtCoder Beginner Contest 154 题解

时间:2020-02-09 22:16:59      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:计算   and   most   clu   expect   row   不用   this   ase   

人生第一场 AtCoder,纪念一下

话说年后的 AtCoder 比赛怎么这么少啊(大雾

AtCoder Beginner Contest 154 题解

A - Remaining Balls

We have A balls with the string S written on each of them and B balls with the string T written on each of them.
From these balls, Takahashi chooses one with the string U written on it and throws it away.
Find the number of balls with the string S and balls with the string T that we have now.

Solution

#include <bits/stdc++.h>
using namespace std;

int a,b;
string s,t,u;

int main() {
    cin>>s>>t>>a>>b>>u;
    if(s==u) cout<<a-1<<" "<<b<<endl;
    else cout<<a<<" "<<b-1<<endl;
}

B - I miss you...

Given is a string S. Replace every character in S with x and print the result.

Solution

算一下字符串长度即可,理论上按char读进来逐个输出应该更短

#include <bits/stdc++.h>
using namespace std;

string s;
int main() {
    cin>>s;
    for(int i=0;i<s.length();i++) cout<<"x";
}

C - Distinct or Not

Given is a sequence of integers \(A_1, A_2, ..., A_N\). If its elements are pairwise distinct, print YES; otherwise, print NO.

Solution

排序应该是比较优雅的方法吧,虽然感觉 std::map 会更短

不对,这 \(1024MB\)的内存,是不是暴力开桶不用压位都能过

#include <bits/stdc++.h>
using namespace std;

int a[200005],n;

int main() {
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    for(int i=1;i<n;i++) {
        if(a[i]==a[i+1]) {
            cout<<"NO"<<endl;
            return 0;
        }
    }
    cout<<"YES"<<endl;
}

D - Dice in Line

We have \(N\) dice arranged in a line from left to right. The \(i\)-th die from the left shows \(p_i\) numbers from \(1\) to \(p_i\) with equal probability when thrown.

We will choose \(K\) adjacent dice, throw each of them independently, and compute the sum of the numbers shown. Find the maximum possible value of the expected value of this sum.

Solution

根据期望的线性性质,很容易发现只要求个最大区间和就可以了。怎么求呢,前缀和啊。

因为没加fixed数字大时飘成科学计数法 WA 了一发,我 TM 真是个憨憨。

#include <bits/stdc++.h>
using namespace std;

int n,k,p[200005];

int main() {
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>p[i], p[i]+=p[i-1];
    int mx=0;
    for(int i=0;i+k<=n;i++) mx=max(mx,p[i+k]-p[i]);
    cout<<setiosflags(ios::fixed)<<setprecision(12)<<(k+mx)*0.5;
}

E - Almost Everywhere Zero

Find the number of integers between \(1\) and \(N\) (inclusive) that contains exactly \(K\) non-zero digits when written in base ten.
\(1 \leq N < 10^{100}\),
\(1 \leq K \leq 3\)

Solution

暴力数位 dp 即可,当然可能有更简单的方法,但我觉得推推公式什么的太麻烦了,还是直接数位 dp 吧

套路性地,设 \(f[i][j]\) 表示长度为 \(i\) 的数字串,有 \(j\) 个非零数位的方案数,转移方程

\[f[i][j] = f[i-1][j] + 9f[i-1][j-1]\]

注意 \(i=0\) 或者 \(j=0\) 的时候需要特判一下

暴力转移预处理出 \(f[i][j]\) 后,我们来统计答案。先把 \(N\) 本身判掉,然后枚举 \(x\) 从哪一位开始比 \(N\) 小,那么这一位之前的就全部确定了(和 \(N\) 一样),这一位讨论一下是 \(0\) 和不是 \(0\) 的情况,每种情况下,这位之后的部分都只约束了非零数字的个数,求和即可得到答案。

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1005;

char str[N];
int n,k,ans,f[N][5];

signed main() {
    cin>>str+1;
    n=strlen(str+1);
    for(int i=1;i<=n;i++) str[i]-='0';
    cin>>k;
    f[0][0]=1;
    for(int i=1;i<=n;i++) {
        f[i][0]=f[i-1][0];
        for(int j=1;j<=3;j++) {
            f[i][j]=f[i-1][j]+9*f[i-1][j-1];
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++) {
        //Calculate a[i] = 0
        if(str[i]) {
            if(k-cnt>=0) ans+=f[n-i][k-cnt];
        }
        //Calculate a[i] > 0
        if(str[i]>1) {
            if(k-cnt-1>=0) ans+=(str[i]-1)*f[n-i][k-cnt-1];
        }
        if(str[i]) ++cnt;
    }
    if(cnt==k) ++ans;
    cout<<ans;
}

F - Many Many Paths

Snuke is standing on a two-dimensional plane. In one operation, he can move by \(1\) in the positive x-direction, or move by \(1\) in the positive y-direction.

Let us define a function \(f(r, c)\) as follows:

\(f(r,c) :=\) (The number of paths from the point \((0, 0)\) to the point \((r, c)\) that Snuke can trace by repeating the operation above)
Given are integers \(r_1, r_2, c_1,\) and \(c_2\). Find the sum of \(f(i, j)\) over all pair of integers \((i, j)\) such that \(r_1 ≤ i ≤ r_2\) and \(c_1 ≤ j ≤ c_2\), and compute this value modulo \((10^9+7)\).
\(1 ≤ r_1 ≤ r_2 ≤ 10^6\),
\(1 ≤ c_1 ≤ c_2 ≤ 10^6\)

Solution

首先单个答案是容易求的,根据高中数学可知 \(f(i,j) = C_{i+j}^i\)

\(g(i,j)\) 是它的二维前缀和,那么原答案一定可以用四个 \(g(i,j)\) 的和差表示

下面考虑如何求 \(g(i,j)\),打印一张数表看一看,很容易想到沿着 \(j\) 维度方向做差试试,观察容易得到

\[g(i,j)-g(i,j-1)=f(i,j+1)\]

于是得到

\[g(i,j) = g(i,0) + \sum_{k=2}^{j-1} f(i,k)\]

考虑到 \(g(i,0)\) 是显然的,而 \(f(i,j)\) 很容易做单维度递推,即

\[f(i,j) = f(i,j-1) \cdot (i+j) \cdot j^{-1}\]

后者用逆元处理即可,每次逆元计算(使用快速幂方法)花费 \(O(\log n)\),于是我们可以在 \(O(n \log n)\) 时间内求出 \(\sum_j f(i,j)\),即求出了 \(g(i,j)\)

总体时间复杂度 \(O(n \log n)\)

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define ll long long
const int mod = 1e+9+7;
ll qpow(ll p,ll q) {
    ll r = 1;
    for(; q; p*=p, p%=mod, q>>=1) if(q&1) r*=p, r%=mod;
    return r;
}
int inv(int p) {
    return qpow(p,mod-2);
}

const int N = 1e+6+5;
int f[N],g[N];

int solve(int i,int m) {
    memset(f,0,sizeof f);
    memset(g,0,sizeof g);
    g[0]=i+1; f[1]=i+1;
    for(int k=2;k<=m+1;k++) f[k]=f[k-1]*(i+k)%mod*inv(k)%mod;
    for(int j=1;j<=m;j++) g[j]=(g[j-1]+f[j+1])%mod;
    return g[m];
}

signed main() {
    int r1,c1,r2,c2;
    cin>>r1>>c1>>r2>>c2;
    --r1; --c1;
    cout<<((solve(r2,c2)-solve(r1,c2)-solve(r2,c1)+solve(r1,c1)%mod+mod)%mod)<<endl;
}

AtCoder Beginner Contest 154 题解

标签:计算   and   most   clu   expect   row   不用   this   ase   

原文地址:https://www.cnblogs.com/mollnn/p/12288901.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!