2025-11-09

CF

Problem - 1739C - Codeforces(1500)(dp)(博弈)

菜菜的,答案都理解了老半天,明明是一个不太难的dp
难在博弈,要想明白平局是BAAB,从大到小分牌

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2e5+10;
LL dp[65][65][3];
int n;
//平局条件:BAAB大到小分牌

void solve(int n)
{
    int k = n / 2;
    dp[0][0][2] = 1;
    for (int i = 0; i <= k;i++){//A
        for (int j = 0; j <= k;j++){//B
            for (int t = 0; t <= 2;t++){//A win,B win,AB
                int turn = (i + j) % 4;
                if(turn==0||turn==3){//给B才有平局
                    if(i<k)
                        dp[i + 1][j][t == 2 ? 0 : t] += dp[i][j][t];
                    if(j<k)
                        dp[i][j + 1][t] += dp[i][j][t];
                }else{//A
                    if(i<k)
                        dp[i + 1][j][t] += dp[i][j][t];
                    if(j<k)
                        dp[i][j + 1][t == 2 ? 1 : t] += dp[i][j][t];
                }
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    solve(60);
    cin >> T;
    while (T--)
    {
        cin >> n;
        int k = n / 2;
        for (int i = 0; i <= 2; i++)
        {
            cout << dp[k][k][i] % mod << " ";
        }
        cout << endl;
    }
}

Problem - 611C - Codeforces(1500)(二维前缀和)

分开计算column和row的可以放置多米诺骨牌的方案数
计算二维前缀和
要注意,直接计算可能会统计突出范围的部分

  • 当计算列的时候,(x-1)->x,少算最上面一行的方案数
  • 当计算行的时候,(y-1)->y,少算最左边一列的方案数
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=510;
int c[N][N], r[N][N],x,y,xx,yy;
string a[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n;i++){
        cin >> a[i];
        a[i] = "#" + a[i];
        for (int j = 1; j <= m;j++){
            c[i][j] = c[i - 1][j] + c[i][j - 1] - c[i - 1][j - 1];
            r[i][j] = r[i - 1][j] + r[i][j - 1] - r[i - 1][j - 1];
            if(a[i][j]=='#')
                continue;
            if(a[i-1][j]=='.')
                c[i][j]++;
            if(a[i][j-1]=='.')
                r[i][j]++;
        }
    }
    int q;
    cin >> q;
    while(q--){
        cin >> x >> y >> xx >> yy;
        int ans = 0;
        ans += c[xx][yy] - c[x][yy] - c[xx][y - 1]+c[x][y-1];
        ans += r[xx][yy] - r[x - 1][yy] - r[xx][y] + r[x - 1][y];
        cout << ans << endl;
    }
}

Problem - 1872E - Codeforces(1500)

前缀和的思想可以解决
分开统计字符串中对应0和1的异或

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=1e5+10;
int a[N];

void solve()
{
    int n,q;
    int l, r,x;
    string s;
    int c0 = 0, c1 = 0;
    cin >> n;
    for (int i = 1; i <= n;i++){
        cin >> a[i];
    }
    cin >> s;
    s = " " + s;
    for (int i = 1; i <= n;i++){
        if(s[i]=='0')
            c0 ^= a[i];
        else
            c1 ^= a[i];
    }
    for (int i = 1; i <= n;i++){
        a[i] ^= a[i - 1];
    }
    cin >> q;
    while(q--){
        int op;
        cin >> op;
        if(op==1){
            cin >> l >> r;
            c0 ^= (a[r] ^ a[l - 1]);
            c1 ^= (a[r] ^ a[l - 1]);
        }else{
            cin >> x;
            if(x==0){
                cout << c0 << " ";
            }else{
                cout << c1 << " ";
            }
        }
    }
    cout << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {
        solve();
    }
}

Problem - 1673C - Codeforces(dp)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 1e9+7;
const int N=4e4+10;
LL f[N];
bool ok(int x){
    vector<int> a;
    while(x){
        a.push_back(x % 10);
        x /= 10;
    }
    vector<int> b = a;
    reverse(b.begin(), b.end());
    return a == b;
}

void solve()
{
    int n;
    cin >> n;
    cout << f[n] << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin >> T;
    f[0] = 1;
    for (int i = 1; i <= 40000;i++){
        if(ok(i)){
            for (int j = i; j <= 40000;j++){
                f[j] = (f[j] + f[j - i]) % mod;
            }
        }
    }
        while (T--)
        {
            solve();
        }
}

方法二:

这个找40000以内的回文数挺妙的

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 1e9+7;
const int N=2e5+10;
LL dp[40010];

void solve()
{
    int n;
    cin >> n;
    cout << dp[n] << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    vector<int> a;
    for (int i = 1; i < 10;i++){
        a.push_back(i);
    }
    for (int i = 1; i < 10;i++){
        a.push_back(i * 11);
    }
    for (int i = 1; i < 10;i++){
        for (int j = 0; j < 10;j++){
            a.push_back(i * 101 + j * 10);
        }
    }
    for (int i = 1; i < 10;i++){
        for (int j = 0; j < 10;j++){
            a.push_back(i * 1001 + j * 110);
        }
    }
    for (int i = 1; i < 4; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            for (int k = 0; k < 10; k++)
            {
                a.push_back(i * 10001 + j * 1010 + k * 100);
            }
        }
    }
    dp[0] = 1;
    for (int i = 0; i < a.size();i++){
        for (int j = 1; j <= 40000;j++){
            if(j>=a[i])
                dp[j] += dp[j - a[i]];
            dp[j] %= mod;
        }
    }
    cin >> T;
    while (T--)
    {
        solve();
    }
}

碎碎念

本来想把数论题单梳理一遍,一早上才梳理两题,下午去预习电工学了
晚上也在肝电工学,好多课落下了。
可能得减少刷题时间啊啊啊啊
数论题单这周找零散时间一点点梳理完吧
新的一周打算开始做字符串题单!

posted @ 2025-11-09 21:09  Seren_blingbling  阅读(1)  评论(0)    收藏  举报