Atcoder Beginner Contest 300 A~E

鼠鼠第一次打这个Atcoder,但一边挂视频一边写代码效率是真的低,只写了三道题

A

在一个序列中找出一个A+B的元素

# include <bits/stdc++.h>
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)
/*
    @see https://atcoder.jp/contests/abc300/tasks/abc300_a
*/
using namespace std;

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, a, b;
    cin >> n >>  a >> b;
    int w[n + 10];
    uf (i, 1, n) 
    {
        cin >> w[i];
        if (w[i] == a + b) cout << i << endl;
    }

    return 0;
}

B

将A向下偏移H次和向左偏移W次,找出一个和B相同的偏移量(h, w), 模拟枚举一下


# include <bits/stdc++.h>
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)
/*
    @see https://atcoder.jp/contests/abc300/tasks/abc300_b
*/
using namespace std;
const int N = 100, M = 100;
char a[N][M], b[N][M], ga[N][M];
int n, m;
bool check()
{
    uf (i, 0, n - 1) uf (j, 0, m - 1) 
    {
        if (a[i][j] != b[i][j]) return false;
    }
    return true;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    uf (i, 0, n - 1) cin >> a[i];
    uf (i, 0, n - 1) cin >> b[i];
    bool ans = check();
    uf (h, 1, n)
    {
        //vertical
        uf (j, 0, m - 1) 
        {
            df (k, n, 1) a[k][j] = a[k - 1][j];
            a[0][j] = a[n][j];
        }
        uf (w, 0, m)
        {
            //horiztical
            uf (j, 0, n - 1)
            {
                df (k, m, 1) a[j][k] = a[j][k - 1];
                a[j][0] = a[j][m];
            }
            ans |= check();
        }
    }
    if (ans) cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}

C

找各个长度的"十字架“的个数,直接枚举

# include <bits/stdc++.h>
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)
/*
    @see https://atcoder.jp/contests/abc300/tasks/abc300_c
*/
using namespace std;
const int N = 110, M = 110;
char g[N][M];
int n, m;

int d[][2] ={ {-1, -1}, {-1, 1}, {1, 1}, {1, -1}};

int  check(int x, int y) 
{
    int ans = 0, t = 1;
    while (true) 
    {
        uf (i, 0, 3)
        {
            int dx = x + d[i][0] * t, dy = y + d[i][1] * t;
            if (dx < 1 || dx > n || dy < 1 || dy > m) return ans;
            if (g[dx][dy] == '.') return ans;
        }
        ans = t;
        t ++;
    }
    return ans;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    uf (i, 1, n) cin >> g[i] + 1;
    vector<int> ans(min(n , m) + 1, 0);
    uf (i, 1, n) 
    {
        uf (j, 0, m - 1) 
        {
            if (g[i][j] == '#')
            {
                ans[check(i, j)] ++;
            }
            uf (i, 1, n) cout << g[i] << endl;
        }
    }
    uf (i, 1, ans.size() - 1) cout << ans[i] << " ";
    return 0;
}

D

题目的数据范围是 1012, 当 a = 2 , b = 3 a = 2, b = 3 a=2,b=3 时, c的最大取值也是在 106

  • 先用线性筛预处理出106 以内的质数
  • 枚举 a 和 c,计算得出b,枚举从a到c中小于等于b的个数即可
# include <bits/stdc++.h>
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)
/*
    @see https://atcoder.jp/contests/abc300/tasks/abc300_d
*/
using namespace std;
const int N = 1e6 + 10;
bool st[N];
vector<int> p;
void init()
{
    uf (i, 2, N - 1)
    {
        if (!st[i]) p.push_back(i);
        for (auto x : p)
        {
            if (x * i > N) break;
            st[x * i] = true;
            if (x % i == 0) break;
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    init();
    cin >> n;
    int m = p.size() - 1;
    int ans = 0;
    uf (i, 0, m) 
    {
        uf (j, i + 2, m) 
        {
            int t = p[i] * p[i] * p[j] * p[j];
            if (t < n)
            {
                int b = n / t;
                uf (k, i + 1, j - 1) 
                {
                    if (p[k] <= b) ans ++;
                }
            } 
            else break;
        }
    }
    cout << ans << endl;
    return 0;
}

E

概率DP

  • 数据范围n在 1018 内,不能开数组存

  • 用dfs搜一下,因为每个状态x只能从 x 2 , x 3 , x 4 , x 5 , x 6 \frac{x}{2}, \frac{x}{3}, \frac{x}{4}, \frac{x}{5}, \frac{x}{6} 2x,3x,4x,5x,6x 转换而来,开一个map存一下搜索的状态

  • 注意概率不是 1 6 \frac{1}{6} 61, 而是 1 5 \frac{1}{5} 51, 因为1点数是不会改变状态,因此每个状态改变时可能穿插多个点数1,不能把点数1忽略

    抛出点数1的概率 p 1 = ∑ i n → ∞ ( 1 6 ) i = 1 1 − 1 6 = 6 5 p_1 = \sum_{i}^{n \to \infty} (\frac{1}{6})^i = \frac{1}{1 - \frac{1}{6}} = \frac{6}{5} p1=in(61)i=1611=56

    与抛出其他点数的概率相乘 p = p 1 ∗ 1 6 = 1 5 p = p_1 * \frac{1}{6} = \frac{1}{5} p=p161=51

# include <bits/stdc++.h>
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)
/*
    @see https://atcoder.jp/contests/abc300/tasks/abc300_e
*/
using namespace std;
const int mod = 998244353;
unordered_map<int, int> mp;
int p;

int dfs (int u)
{
    if (u == 1) return 1;
    if (u <= 0) return 0;
    if (mp.count(u)) return mp[u];
    int ans = 0;
    uf (i, 2, 6)
    {
        if (u % i == 0)
        {  
            ans = (ans +  dfs(u / i) * p % mod) % mod;
        } 
    }
    mp[u] = ans;
    return ans;
}

signed main()
{

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    auto qmi = [&](int x, int y) {
        int ans = 1;
        while(y) 
        {
            if (y & 1) ans = ans * x % mod;
            x = x*x % mod;
            y >>= 1;
        }
        return ans;
    };
    p = qmi(5, mod - 2);
    int n;
    cin >> n;
    cout << dfs(n) << endl;
    return 0;
}

看到别的题解有用质因数进行dp,确定2,3,5这三个质因数的个数,然后用一个四维数组做一个dp

  • n = 2 a ⋅ 3 b ⋅ 5 c n = 2^a \cdot 3^b \cdot 5^c n=2a3b5c, a的值最多是60, 即 a ≤ 60 , a + b + c ≤ 60 a \le 60, a + b + c \le 60 a60,a+b+c60
  • d p [ i , j , k , h ] dp[i, j, k, h] dp[i,j,k,h] 表示第i次转化到质因数个数分别是j,k,h的概率
  • 最后只要统计 d p [ i , a , b , c ] dp[i, a, b, c] dp[i,a,b,c] 的概率即可
# include <bits/stdc++.h>
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)

using namespace std;
const int mod = 998244353, N = 70;
int p, n, a, b, c, ans;
int dp[N][N][N][N];

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    auto qmi = [&](int x, int y) {
        int ans = 1;
        while(y) 
        {
            if (y & 1) ans = ans * x % mod;
            x = x*x % mod;
            y >>= 1;
        }
        return ans;
    };
    p = qmi(5, mod - 2);
    dp[0][0][0][0] = 1;
    cin >> n;
    while (n % 2 == 0) a ++, n /= 2;
    while (n % 3 == 0) b ++, n /= 3;
    while (n % 5 == 0) c ++, n /= 5;
    if (n == 1)
    {
        int m = N - 3;
        uf (i, 0, m) uf (j, 0, m) uf(k, 0, m) uf (h, 0, m)
        {
            int  t = dp[i][j][k][h];
            dp[i + 1][j + 1][k][h] += t * p % mod;
            dp[i + 1][j][k + 1][h] += t * p % mod;
            dp[i + 1][j][k][h + 1] += t * p % mod;
            dp[i + 1][j + 2][k][h] += t * p % mod;
            dp[i + 1][j + 1][k + 1][h] += t * p % mod;
        }
        uf (i, 0, N - 1) ans += dp[i][a][b][c], ans %= mod;
    }
    cout << ans << endl;
    return 0;
}

梦会枯 毕竟夜有 尽头
醒来后 开怀享受 腐朽
每天都 有个我化 作 乌 有

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值