AtCoder Beginner Contest 215(补题)

C - One More aab aba baa

题目链接: link.

题意:

给一个字符串,让你输出由该字符串的字母组成的所有全排列中的第k个全排列是什么?

思路:

#include <bits/stdc++.h>
using namespace std;
string s;
int k;
int a[8];
int main() {
    cin >> s >> k;
    sort(s.begin(), s.end());
    int len = s.size();
    for (int i = 0; i < len; i++) {
        a[i] = s[i] - 'a';
    }
    int cnt = 1;
    while (next_permutation(a, a + len)) {
        cnt++;
        if (cnt == k) break;
    }
    for (int i = 0; i < len; i++) {
        printf("%c", a[i] + 'a');
    }
    return 0;
}

D - Coprime 2

题目链接: link.

题意:

给你一个长度为n的数组 a 1 a_1 a1 a n a_n an,问你 1 1 1 m m m中那些数,与 a a a数组所有元素取最大公约数gcd,是1

思路:

a a a中元素质因数分解,把里面的质因子取出来,用质因子来筛 1 1 1 m m m中符合题意的数,也就是与这些质因子不是倍数关系的数。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> a[N];
int n, m;
int st[N];
int main() {
    cin >> n >> m;
    vector<int> res;
    for (int p = 0; p < n; p++) {
        int x;
        scanf("%d", &x);
        for (int i = 2; i <= x / i; i++) {
            if (x % i == 0) {
                while (x % i == 0) {
                    x /= i;
                }
                res.push_back(i);
            }
        }
        if (x > 1) res.push_back(x);
    }
    vector<int> ans;
    sort(res.begin(), res.end());
    res.erase(unique(res.begin(), res.end()), res.end());

    for (int i = 1; i <= m; i++) {
        if (st[i]) continue;
        for (int j = 0; j < res.size(); j++) {
            int x = res[j];
            int y = 1;
            while (y * x <= m) {
                st[y * x] = 1;
                y++;
            }
        }
    }
    for (int i = 1; i <= m; i++) {
        if (!st[i]) ans.push_back(i);
    }
    cout << ans.size() << endl;
    for (int i = 0; i < ans.size(); i++) {
        cout << ans[i] << endl;
    }

    return 0;
}

E - Chain Contestant

题目链接: link.

题意:

给一个长度为 n n n的字符串,问有多少种子序列满足,在字符串中,相同字母的位置是连续的.

思路:

题目说了,最多10个字母,长度最大1000
所以可以用状压 d p dp dp来想
定义 f ( i , j , k ) f(i,j,k) f(i,j,k),到了字符串的 i i i位置, j j j字母, k k k为10个字母选与没选二进制数字。
f ( i , j , k ) = f(i,j,k)= f(i,j,k)= f ( i − 1 , j , k ) f(i-1,j,k) f(i1,j,k),这是不选 i i i号位置的字母
f ( i , c u r , 1 < < c u r ) + + f(i,cur,1 << cur) ++ f(i,cur,1<<cur)++这是第 i i i号位置,字母 c u r cur cur,选的情况
如果选了这个字母,那么这个字母之前出现过的话,必须在前一个位置,必须连续。那么就是 f ( i , c u r , j ) + = f ( i − 1 , c u r , j ) f(i,cur,j )+= f(i - 1,cur,j) f(i,cur,j)+=f(i1,cur,j)
含义就是到了 i i i号位置了,选cur这个字母,二进制下是 j j j,在 i − 1 i-1 i1决策时,选了 c u r cur cur,二进制数仍然是 j j j
如果这个字母没出现过,那么就标记这个字母出现了,利用或运算,来对二进制下的数字进行标记
f ( i , c u r , j ∣ 1 < < c u r ) + = f ( i − 1 , k , j ) f(i,cur,j | 1 << cur) += f(i - 1,k,j) f(i,cur,j1<<cur)+=f(i1,k,j)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 998244353;
ll f[1025][10][1025];
int n;
string s;

int main() {
    cin >> n >> s;
    for (int i = 1; i <= n; i++) {
        int cur = s[i - 1] - 'A';
        for (int j = 0; j < 1 << 10; j++) {
            for (int k = 0; k <= 9; k++) {
                f[i][k][j] = f[i - 1][k][j];
            }
        }
        (f[i][cur][1 << cur] += 1) %= mod;
        for (int j = 0; j < 1 << 10; j++) {
            if (j & (1 << cur)) {
                (f[i][cur][j] += f[i - 1][cur][j]) %= mod;
            } else {
                for (int k = 0; k <= 9; k++) {
                    (f[i][cur][j | 1 << cur] += f[i - 1][k][j]) %= mod;
                }
            }
        }
    }
    ll res = 0;
    for (int i = 0; i <= 9; i++) {
        for (int j = 0; j < 1 << 10; j++) {
            (res += f[n][i][j]) %= mod;
        }
    }
    cout << res % mod << endl;
    return 0;
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值