前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【算法竞赛】AtCoder Beginner Contest 171F 172E 172F

【算法竞赛】AtCoder Beginner Contest 171F 172E 172F

作者头像
Livinfly
发布2023-01-10 15:03:52
2300
发布2023-01-10 15:03:52
举报
文章被收录于专栏:Livinfly

171F - Strivore

代码语言:javascript
复制
#pragma GCC optimize(2)

#include <bits/stdc++.h>

#define fi first
#define se second
#define mkp(x, y) make_pair((x), (y))
#define all(x) (x).begin(), (x).end()

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 2e6+10, P = 1e9+7;

int n, m;
string s;
int fact[N], factInv[N];

int qpm(int a, int b) {
    int ans = 1;
    while(b) {
        if(b & 1) ans = (LL)ans*a%P;
        a = (LL)a*a%P;
        b >>= 1;
    }
    return ans;
}
void PrevCalu() {
    fact[0] = 1;
    for(int i = 1; i <= n+m; i ++)
        fact[i] = (LL)fact[i-1]*i%P;
    factInv[n+m] = qpm(fact[n+m], P-2);
    for(int i = n+m-1; i >= 0; i --)
        factInv[i] = (LL)factInv[i+1]*(i+1)%P;
}
int C(int n, int m) {
    return (LL)fact[n]*factInv[n-m]%P*factInv[m]%P;
}
void solve() {
    cin >> m >> s;
    n = s.size();
    PrevCalu();
    int res = 0;
    for(int i = n; i <= n+m; i ++) {
        res = ((LL)res+(LL)qpm(26, n+m-i)*qpm(25, i-n)%P*C(i-1, n-1)%P)%P;
    }
    cout << res << '\n';
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout << fixed;  // << setprecision(20); // double
    // freopen("i.txt", "r", stdin);
    // freopen("o.txt", "w", stdout);
    // int Tcase;
    // cin >> Tcase; // scanf("%d", &Tcase);
    // while (Tcase--) 
    solve();
    return 0;
}

/*
C(i-1, n-1) 最后一位的位置确定了

n+|s|的字符串的子序列有s的个数
求方案,假设得到最终子串,贪心地选,即取连续的子串的第一个字母
xxxxxx|xxxx
子序列的最后到|的前一位,后面都有26种选法,前面都有25种选法
*/

172E - NEQ

代码语言:javascript
复制
#pragma GCC optimize(2)

#include <bits/stdc++.h>

#define fi first
#define se second
#define mkp(x, y) make_pair((x), (y))
#define all(x) (x).begin(), (x).end()

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 5e5+10, P = 1e9+7;

int n, m;
int fact[N], factInv[N];

int qpm(int a, int b) {
    int ans = 1;
    while(b) {
        if(b & 1) ans = (LL)ans*a%P;
        a = (LL)a*a%P;
        b >>= 1;
    }
    return ans;
}
void PrevCalu() {
    fact[0] = 1;
    int mx = max(n, m); // ...
    for(int i = 1; i <= mx; i ++) 
        fact[i] = (LL)fact[i-1]*i%P;
    factInv[mx] = qpm(fact[mx], P-2);
    for(int i = mx-1; i >= 0; i --)
        factInv[i] = (LL)factInv[i+1]*(i+1)%P;
}
int A(int n, int m) {
    return (LL)fact[n]*factInv[n-m]%P;
}
int C(int n, int m) {
    return (LL)fact[n]*factInv[n-m]%P*factInv[m]%P;
}
void solve() {
    cin >> n >> m;
    PrevCalu();
    int res = 0;
    for(int i = 0; i <= n; i ++) {
        int x = (LL)C(n, i)*A(m, i)%P*A(m-i, n-i)%P*A(m-i, n-i)%P;
        res = ((LL)res + ((i&1) ? -1 : 1)*x)%P;
        res = ((LL)res+P)%P;
    }
    cout << res << '\n';
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout << fixed;  // << setprecision(20); // double
    // freopen("i.txt", "r", stdin);
    // freopen("o.txt", "w", stdout);
    // int Tcase;
    // cin >> Tcase; // scanf("%d", &Tcase);
    // while (Tcase--) 
    solve();
    return 0;
}
/*


从全错排的推导可以过来
https://zhuanlan.zhihu.com/p/133818995

1. 容斥原理
    也先和普通的全错排证明一样,先确定某几个位置A, B相同 a_i == b_i --- C(n, i)
    在把这i个数填上                                              --- A(m, i)
    在剩下的位置A和B都随便放                                      --- A(m-i, n-i) * A(m-i, n-i)


(DP我现在也不是很看得懂,只先写了普通错排的DP)
2. DP
    f[i], 为i位错排的方案数
    对即将要放的数,同普通的全错排的考虑
    将i放在k的位置,若k在i的位置,那么就不用考虑i和k了,剩下的错排
    再考虑有i-1种可能这样的情况                                   --- (i-1)*f[i-2]
    将i放在k的位置,而k不在i的位置,那么不管i(i已经合法,即已经错排)
    而这种情况,我们预设k不在i,那就可以把i的位置当作k的原本的位置
    除i外的i-1个数错排的方案数                                    --- (i-1)*f[i-1]
*/

172F - Unfair Nim

需要先知道Nim的结论

代码语言:javascript
复制
#pragma GCC optimize(2)

#include <bits/stdc++.h>

#define fi first
#define se second
#define mkp(x, y) make_pair((x), (y))
#define all(x) (x).begin(), (x).end()

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

int n;

void solve() {
    cin >> n;
    vector<LL> a(n);
    for(auto &x : a) cin >> x;
    LL Xor = 0, And = 0, Add = a[0]+a[1];
    for(int i = 2; i < n; i ++) Xor ^= a[i];
    // a+b = a^b + 2*(a&b)
    And = Add-Xor;
    // Xor是期望的值,而不是式子里确定的值,导致以下不合法的情况,包括下面需要判断的不合法也是因为这个
    if(Xor > Add || And % 2) {
        cout << "-1\n";
        return;
    }
    And /= 2;
    /*
        a^b a&b     a   b
         0   0  ->  0   0
         1   1  ->  x   x   (不合法)
         0   1  ->  1   1
         1   0  ->  不 同
    */
    LL ans = And;
    for(int i = 60; i >= 0; i --) {
        int xx = Xor>>i&1, yy = And>>i&1;
        if(xx && yy) {
            cout << "-1\n";
            return;
        }
        if(xx && !yy && (ans|1LL<<i) <= a[0]) {
            ans |= 1LL<<i;
        }
    }
    if(!ans || ans > a[0]) {
        cout << "-1\n";
        return;
    }
    cout << a[0]-ans << '\n';
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout << fixed;  // << setprecision(20); // double
    // freopen("i.txt", "r", stdin);
    // freopen("o.txt", "w", stdout);
    // int Tcase;
    // cin >> Tcase; // scanf("%d", &Tcase);
    // while (Tcase--) 
    solve();
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023年01月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 171F - Strivore
  • 172E - NEQ
  • 172F - Unfair Nim
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档