AtCoder Beginner Contest 242 题解

A - T-shirt

  • 思路
    • 要么一定得到,要么不可能得到,要么按题意概率直接列公式算概率
  • 经验教训
  • AC代码

#define int long long

void solve() {
    int a,b,c,x;
    cin>>a>>b>>c>>x;
    cout<<fixed<<setprecision(9);
    if (x<=a) cout<<1<<'\n';
    else if (x>b) cout<<0<<'\n';
    else{
//        double ans = 0;
//cout<<111;
        cout<<(double)c/(b-a)<<'\n';
    }
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    solve();

}

B - Minimize Ordering

  • 思路
    • 字典储存个数,然后按字典序从小到大打印即可
  • 经验教训
  • AC代码
#define int long long
void solve() {
    string s;
    cin>>s;
    map<char,int> m;
    for (int i = 0; i < s.size(); ++i) {
        m[s[i]]++;
    }
    string ans;
    for (auto mm:m) {
        for (int i = 0; i < mm.second; ++i) {
            ans+=mm.first;
        }
    }
    cout<<ans;
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    solve();

}

C - 1111gal password

  • 思路
    • 本来以为挺难的,其实就是个dp
    • dp[n][k]表示一共有n个数字时,最高位数字是k时,所以能组出来的排序数
    • dp递推公式看代码应该很快就能看懂,比如2xxx所能组成的符合题意排序个数就会等于1xx+2xx+3xx。而1和9比较特殊,1xxx=1xx+2xx;9xxx=9xx+8xx。
    • 初始化n=2的情况即可
    • 记得随时取模
  • 经验教训
  • AC代码
#define int long long

const int maxn = 1e6 + 5;
int dp[maxn][10];
int mod = 998244353;

void solve() {
    int n;
    cin >> n;
    dp[2][1] = 2;
    for (int i = 2; i <= 8; ++i) {
        dp[2][i] = 3;
    }
    dp[2][9] = 2;
    for (int i = 3; i <= n; ++i) {
        for (int j = 1; j <= 9; ++j) {
            if (j == 1) dp[i][j] = (dp[i - 1][1] + dp[i - 1][2]) % mod;
            else if (j == 9) dp[i][j] = (dp[i - 1][8] + dp[i - 1][9]) % mod;
            else dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j] + dp[i - 1][j + 1]) % mod;
        }
    }
    int ans = 0;
    for (int i = 1; i <= 9; ++i) {
        ans+= (dp[n][i])%mod;
    }
    cout<<(ans)%mod;
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    solve();

}

D - ABC Transform

  • 思路

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rW3LhmrS-1646546097921)(https://secure2.wostatic.cn/static/jADJCBj9nMgvfojZB1w8Zs/image.png)]

    • 整个搜索过程看成是一个类似二叉树的东西,每一层代表经过t次变化后得到的结果。0代表A,1代表B,2代表C。每一层的第k个位置通过(k+1)/ 2可以找到他的父节点,一层一层上去最终找到最初的。
    • 如果设m为从最初走到最后的一层的第k个位置所经过的数之和(每一层+1或者+2),那么(最初位置的数+m)%3就是最后的答案
  • 经验教训

    • (k%2)^1: ^1的效果为1变成0,0变成1
  • AC代码

#define int long long

const int maxn =1e5+5;
int a[maxn];

//void solve(string &s) {
//
//}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    string s;int q;
    cin>>s>>q;
    for (int i = 0; i < s.size(); ++i) {
        if (s[i] =='A' ) a[i+1] = 0;
        if (s[i] =='B' ) a[i+1] = 1;
        if (s[i] =='C' ) a[i+1] = 2;
    }
    map<int,char> m;
    m[0] = 'A',m[1]='B',m[2] = 'C';
    for (int i = 0; i < q; ++i) {
        int t,k;cin>>t>>k;
        int sum = 0;
        while (t>0 && k!=1){
            sum += ((k%2)^1)+1;
            sum%=3;
            k = (k+1)/2;
            t--;
        }
        sum+=t;
        cout<<m[(a[k]+sum)%3]<<'\n';
    }
}

E - (∀x∀)

  • 思路
    • 我们可以首先预处理出长度为n的串所构成的全部回文串个数,比如长度为1,那么就只能是A,B…,Z一共26个,长度为2,AA,BB,…ZZ一共26个,长度为3,A?A,B?B…Z?Z,其中?可以为长度为1的回文串个数,所以一共为26*26个,以此类推下去
    • 以串CBDDD举例,我们可以知道AxxxA,BxxxB对应的所有情况一定是合法,所以我们首先得到 ( i n t ) C − A (int) C-A (int)CA* 长度为3的回文串个数(2626),即ans+=226*26。走到B,我们知道AxA对应的所有情况一定是合法的,所以 ans+= ((int)B-A)*26。然后走到最中间,特判CBDBC是否合法,如果合法就+1,不合法就不+1,输出ans即可
  • 经验教训
  • AC代码
#define int long long

const int maxn = 1e6 + 5;
int dp[maxn];
int mod = 998244353;

void pre() {
    dp[0] = 1;
    for (int i = 1; i <= 1000000; ++i) {
        dp[i] = (dp[i - 1] * 26) % mod;
    }
}

void solve() {
    string s;
    int n;
    cin >> n >> s;
    if (n==1){
        cout<<(s[0]-'A')+1<<'\n';
        return;
    }
    int ans = 0;
    if (s.size() % 2 == 0) {
        int len = s.size() / 2 - 1;
        for (int i = 0; i < s.size() / 2; ++i) {
            int me = s[i] - 'A';
            ans += (me * dp[len] % mod);
            ans %= mod;
            len--;
        }
    } else {
        int len = (s.size()) / 2;
        for (int i = 0; i < s.size() / 2 + 1; ++i) {
            int me = s[i] - 'A';
//            cout<<dp[len]<<" "<<len<<" "<<me*dp[len]<<endl;
            ans += ((me * dp[len]) % mod);
            ans %= mod;
            len--;
        }
    }
    int ret = ans % mod;
    int left, right;
    if (n % 2) {
        left = n / 2 - 1, right = n / 2 + 1;
    } else {
        left = n / 2 - 1, right = n / 2;
    }
    while (s[left] == s[right] && left > 0) {
        left--;
        right++;
    }
    if (s[left] <= s[right]) ret++;
    cout << ret << '\n';
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    cin >> t;
    pre();
    for (int i = 0; i < t; ++i) {
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值