首页 > 其他分享 >AtCoder Beginner Contest(abc) 324

AtCoder Beginner Contest(abc) 324

时间:2023-11-16 22:33:55浏览次数:39  
标签:AtCoder abc int long 字符串 324 序列 tie define




B - 3-smooth Numbers

难度: ⭐

题目大意

给定一个数字n, 问是否可以找到两个数x和y, 使得 n = 2x3y;

解题思路

因为n的范围最大到1e18, 所以只需要暴力找x和y即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5+10;
typedef pair<int,int> PII;
int n, m, idx;
signed main(){
    cin >> n;
    for(int i = 0; i <= 64; i++){
        for(int j = 0; j <= 64; j++){
            int x = pow(2, i), y = pow(3, j);
            if(x * y == n){
                cout << "Yes";
                return 0;
            }
        }
    }
    cout << "No";
    return 0;
}




C - Error Correction

难度: ⭐⭐

题目大意

给定一个由小写字母组成字符串S, 我们可以将其修改为字符串T, 由S变为T的合法方案有四种而且只能用其中一个: 一是不变, 二是插入一个小写字母, 三是删除一个小写字母, 四是修改一个小写字母; 给出n个字符串T', 请问其中有多少个是符合合法方案的字符串T;

解题思路

除了不变以外, 我们发现其他三种修改方案的容错率只有1个小写字母; 所以我们可以用双指针遍历S和当前字符串T', 对于每个字符串T'我们只允许它和S的差异只出现一次, 出现差异后我们根据T'和S的长度来判断T'可能是S通过哪种方案得到的, 根据那个方案对当前的遍历进行修补, 如果后面又出现差异就可以直接判错了;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5+10;
typedef pair<int,int> PII;
int n, m, idx;
int f[N], st[N];
bool check(int u){
    for(int i = 0; i <= 9; i++) st[i] = 0;
    for(int i = 1; i <= n; i++) {
        st[f[i]]++;
    }
    for(int i = 1; i <= n; i++){
        int x = u % 10;
        u /= 10;
        if(st[x]) st[x]--;
        else return false;
    }
    return true;
}
signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        char c;
        cin >> c;
        f[i] = c - '0';
    }
    int maxn = 1;
    for(int i = 1; i <= n; i++) maxn *= 10;
    for(int i = 0; i * i <= maxn; i++){
        int x = i * i;
        if(check(x)){
            idx++;
        }
    }
    cout << idx;
    return 0;
}




D - Square Permutation

难度: ⭐⭐⭐

题目大意

给定n个数字, 我们可以对其进行排列, 对于其中一种排列(p1, p2 ... pn), 我们可以得到一个数Q = p1 + p2 * 10 + p3 * 102 ... pn * 10(n-1); 如果Q是一个平方数, 那么这个序列就被称为合法的, 请问存在多少种合法的序列; 如果有多个序列得到了同一个平方数, 那么这些序列只会被记为1个;

解题思路

本题的n最大为13, 所以肯定不能考虑全排列; 题目有句话就已经提示了做法, 如果有多个序列得到了同一个平方数, 那么这些序列只会被记1次; 所以我们不应该去找序列, 而是看有多少种平方数可以被凑出; 因为Q的最大范围是1e14, 所以找其中的平方数只需要1e7的复杂度就可以了; 对于每个平方数Q, 我们遍历Q的每一位数x, 给出的n个序列中是否还有x, 如果有就让它的数量减一, 否则就说明凑不出来;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5+10;
typedef pair<int,int> PII;
int n, m, idx;
int f[N], st[N];
bool check(int u){
    for(int i = 0; i <= 9; i++) st[i] = 0;
    for(int i = 1; i <= n; i++) st[f[i]]++;
    for(int i = 1; i <= n; i++){
        int x = u % 10;
        u /= 10;
        if(st[x]) st[x]--;
        else return false;
    }
    return true;
}
signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        char c;
        cin >> c;
        f[i] = c - '0';
    }
    int maxn = 1;
    for(int i = 1; i <= n; i++) maxn *= 10;
    for(int i = 0; i * i <= maxn; i++){
        int x = i * i;
        if(check(x)){
            idx++;
        }
    }
    cout << idx;
    return 0;
}




E - Joint Two Strings

难度: ⭐⭐⭐

题目大意

给定1个字符串S和n个字符串Ti; 问存在多少种二元组(i, j), 使得S的字符串Ti + Tj的一个子序列; (注意是子序列而不是子串);

解题思路

因为问的是子序列, 那么我们可以求出每个字符串Ti对于S的前缀子序列的长度和后缀子序列的长度; 那么我们在找二元组的过程中, 设S的长度为len, Ti对于S的前缀子序列长度为x, 那么我们只需要从其他字符串中找出其对于S的后缀子序列长度至少为(len - x)的Tj即可; 这个可以用前缀和来维护数量;
eg: 字符串S为"basdh", 字符串T为"dbsdahd", T对于S的前缀子序列是"bah", 长度为3; 后缀子序列是"hds", 长度为3;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 5e5+10;
typedef pair<int,int> PII;
int n, m, idx;
string s;
int st[N], ed[N];
int h[N], t[N];
signed main(){
    cin >> n >> s;
    for(int i = 1; i <= n; i++){
        string str;
        cin >> str;
        int k = 0;
        for(int j = 0; j < str.size(); j++){
            if(str[j] == s[k]){
                k++;
                st[i]++;
            }
        }
        k = s.size() - 1;
        for(int j = str.size() - 1; j >= 0; j--){
            if(str[j] == s[k]){
                k--;
                ed[i]++;
            }
        }
    }
    for(int i = 1; i <= n; i++) t[ed[i]]++;
    for(int i = s.size(); i >= 0; i--) t[i] += t[i+1]; // 求前缀和
    for(int i = 1; i <= n; i++){
        int a = st[i], b = s.size() - a;
        if(a == s.size()) idx += n;
        else idx += t[b];
    }
    cout << idx;
    return 0;
}




F - Beautiful Path

难度: ⭐⭐⭐⭐

题目大意

一个有向图中有n和节点和m条边, 对于每条边一定是有编号小的点指向编号大的点; 每条边有两个属性b和c, 对于一条路径, 他的价值是路径中所有边的b的和除以c的和, 问从1到n的路径中价值最大的路径的价值是多少;

解题思路

一道0/1分数规划的板子题, 比如说有n个物品,每个物品有两个权值a和b,然后让你选出任意件数的物品,使得这些物品中两个权值的和之间的比值最大; 分数规划一般都是用二分进行求解;
设当前已经选择了一条1到n的路径, 其中属性b的和为sum, 属性c的和为tot, 当前的二分答案为mid, 二分答案是最大价值; 那么一定存在 sum / tot <= mid; 移项就得到了sum - tot * mid <= 0; sum的属性b的和, tot * mid是属性c * mid的和; 这样我们就把路径问题转变了每条边的问题, 所以我们就可以把边的权值设为b - c * mid, 然后求最长路径就可以了; 因为本题不可能存在环, 所以最大路径可以用dp来求; 在二分的check函数中我们就看是否存在一条路径的sum - tot * mid > 0, 如果大于0说明最佳情况可能更大, 否则就更小, 一个普通的二分逻辑;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 5e5+10;
typedef pair<int,int> PII;
int n, m, idx;
struct Node{
    int u;
    double w;
};
vector<Node> edge[N];
int u[N], v[N], b[N], c[N];
double d[N];
bool check(double mid){
    for(int i = 1; i <= n; i++){
        edge[i].clear();
        d[i] = -1e15;
    }
    
    for(int i = 1; i <= m; i++) {
        double w = 1.0 * b[i] - c[i] * mid;
        edge[v[i]].push_back({u[i], w});
    }
    d[1] = 0;
    for(int i = 1; i <= n; i++){
        for(Node t : edge[i]){
            int x = t.u;
            double w = t.w;
            d[i] = max(d[i], d[x] + w);
        }
    }
    if(d[n] > 1e-11) return true;
    else return false;
}
signed main(){
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        cin >> u[i] >> v[i] >> b[i] >> c[i];
    }
    double l = 0, r = 1e4;
    while(r - l > 1e-11){
        double mid = (l + r) / 2;
        if(check(mid)) l = mid;
        else r = mid;
    }
    printf("%.11lf", l);
    return 0;
}

标签:AtCoder,abc,int,long,字符串,324,序列,tie,define
From: https://www.cnblogs.com/mostimali/p/17837434.html

相关文章

  • abc280F - Pay or Receive(判断是否全为零环)
    https://atcoder.jp/contests/abc280/tasks/abc280_f对于每一个连通块单独处理,首先判断是否全为0环,可以用bfs判断。从一个点出发计算其他点到它的最短距离,如果存在一个不唯一,说明存在非零环。然后计算距离的时候直接-d[x]+d[y]即可#include<cstdio>#include<algorithm>#incl......
  • abc327F - Apples(线段树)
    https://atcoder.jp/contests/abc327/tasks/abc327_f我们将时间看作x轴,位置看作y轴,那么我们随着时间增加,维护新加的点对区间的贡献,同时减去过时的点,线段树区间加法维护最大值即可。#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<map>#incl......
  • AT_abc215_d
    基本概括当解决这个问题时,我们需要找到满足条件的整数\(k\),使得对于给定的序列\(A=(A_1,A_2,\dots,A_N)\)中的每个数\(A_i\),都满足\(\gcd(A_i,k)=1\)。实现思路首先,我们可以观察到,如果\(k\)是\(A_i\)的质因数或其倍数,那么\(\gcd(A_i,k)\)将不等于1。因此,我们可......
  • [题解]AT_abc267_f [ABC267F] Exactly K Steps
    大家好,我是毒瘤,喜欢用玄学算法过题。发现题解区没有这个做法,于是来发一篇。思路不难发现如果一个点对\((u,v)\)的距离为\(d\),那么在这棵树以\(u\)为根时,\(v\)的深度为\(d\)。于是考虑换根DP。首先思考如何计算答案。显然我们可以将查询离线下来,然后当换根到以\(u\)......
  • [ABC230F] Predilection
    题目描述:芷萱姐姐有一个长度为\(N\)的数列\(A_i\)。你可以进行若干次,最多\(N-1\)次操作,选择相邻的两个数,删去他们,并在原位置放上他们两个的和。现在你需要求出可能产生的序列个数。数据范围:\(1\leN\le2\times10^5\)\(|A_i|\le10^9\)思路:我们首先会发现一件......
  • AtCoder Beginner Contest(abc) 328
    B-11/11难度:⭐题目大意在某个世界一年有n个月,每个月有di天,问有多少个日期,该日期和月份组成的数字都是一样的;eg:11月的1日,22月的22日;解题思路暴力就行;神秘代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;typedefpair<int......
  • AtCoder Beginner Contest 325
    A-Takahashisan#include<bits/stdc++.h>usingnamespacestd;#definelllonglongusingvi=vector<int>;intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);strings,t;cin>>s>>t;cout<......
  • AT_abc230_f [ABC230F] Predilection 题解
    prelogue各位在比赛的时候一定要坚信自己的式子,然后去考虑自己的实现是不是挂了。本人在今天模拟赛的时候质疑自己的式子然后不看实现100->0。analysis考虑对这个给定数组进行前缀和,然后就将问题转化成为了求这个前缀和数组的子序列的个数。对于求子序列,我们很轻松可以写出......
  • [题解]AT_abc328_f [ABC328F] Good Set Query
    思路带权并查集模板。如果对于一个三元组\((a,b,c)\)如果它能够添加到\(S\)中一定满足如下条件中的一条:\(X_a,X_b\)满足其中有一个是「不确定」的。在这里\(X_i\)「不确定」指\(X_i\)没有与其它的任意\(X_j\)有关系。\(X_a,X_b\)有间接或直接的关系,但是能计算......
  • Toyota Programming Contest 2023#7(AtCoder Beginner Contest 328)
    ToyotaProgrammingContest2023#7(AtCoderBeginnerContest328)A.NotTooHard题意:将给定的数列\(a\)中数值小于\(x\)的数累加。解题思路:模拟。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;voidsolve(){ intn,x; cin>>n>>x;......