几道题(hdu5671 && hdu5672 && hdu5673)

hdu5671 Matrix
思路
* 所有操作都是整行或整列,所以矩形的两个维度可以独立处理
* 对于交换我们用一个映射表表示当前的第i行(列)是原矩形的第多少行(列),对于加数我们用一个数组记录原矩形第i行加了多少,为什么是原矩形呢?因为对现矩形的所有操作本质上是对原矩形的操作
代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 7;
int T, n, m, q, a[N][N], x[N], y[N], dx[N], dy[N], id, xx, yy;
void Case(int id) {
    if (id == 1) swap(x[xx], x[yy]);
    if (id == 2) swap(y[xx], y[yy]);
    if (id == 3) dx[x[xx]] += yy;
    if (id == 4) dy[y[xx]] += yy;
}
int main() {
    //freopen("in.txt", "r", stdin);
    cin >> T;
    while (T--) {
        cin >> n >> m >> q;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                scanf("%d", a[i] + j);
            }
        }
        for (int i = 0; i < n; i++) x[i] = i;
        for (int i = 0; i < m; i++) y[i] = i;
        memset(dx, 0, sizeof(dx));
        memset(dy, 0, sizeof(dy));
        while (q--) {
            scanf("%d%d%d", &id, &xx, &yy);
            xx--;
            if (id <= 2) yy--;
            Case(id);
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                int xx = x[i];
                int yy = y[j];
                printf("%d%c", a[xx][yy] + dx[xx] + dy[yy], j == m - 1? '\n' : ' ');
            }
        }
    }
    return 0;
}

hdu5672 String
思路
* 如果[l, r]表示的字串符合要求,那么[l, r+1]也符合要求
* 令f(l)表示[l, r]符合要求的最小的r,那么f(l)单调不降
代码

#include <bits/stdc++.h>
using namespace std;
int cnt[26], num, r, k, T, n;
char s[1234567];
long long ans;
int main() {
    //freopen("in.txt", "r", stdin);
    cin >> T;
    while (T--) {
        scanf("%s", s);
        cin >> k;
        n = strlen(s);
        for (int i = 0; i < n; i++) s[i] -= 'a';
        ans = num = r = 0;
        memset(cnt, 0, sizeof(cnt));
        for (int l = 0; l < n; l++) {
            while (num < k && r < n) if (++cnt[s[r++]] == 1) num++;
            if (num < k) break;
            ans += n - r + 1;
            if(--cnt[s[l]] == 0) num--;
        }
        cout << ans << endl;
    }
    return 0;
}

hdu5673 Robot
思路
* 要保证最后回到原点,那么向左走的步数必等于向右走的步数
* 假设有i秒原地不动,那么相当于有 n2i 秒不是向左走就是向右走,同时要求不能出现在原点左边,这和进栈出栈序列总数是一样的,即方案总数是卡特兰数
* 答案等于 n2i=0C2incatalan(i)
代码

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7, N = 1e6 + 7;
long long ans;
int n, fac[N], invfac[N], cat[N], T;
long long powermod(long long a, int n, int m) {
    long long ans = 1;
    for (; n; n >>= 1) {
        if (n & 1) ans = ans * a % m;
        a = a * a % m;
    }
    return ans;
}
void init() {
    fac[0] = invfac[0] = 1;
    for (int i = 1; i < N; i++) {
        fac[i] = (long long)fac[i - 1] * i % mod;
        invfac[i] = invfac[i - 1] * powermod(i, mod - 2, mod) % mod;
    }
    cat[0] = cat[1] = 1;
    for (int i = 2; i < N; i++) {
        cat[i] = cat[i - 1] * (4ll * i - 2) % mod * powermod(i + 1, mod - 2, mod) % mod;
    }
}
long long C(int n, int m) {
    return (long long)fac[n] * invfac[m] % mod * invfac[n - m] % mod;
}
int work() {
    ans = 0;
    for (int i = 0; i * 2 <= n; i++) {
        ans = (ans + C(n, i * 2) * cat[i]) % mod;
    }
    return ans;
}
int main() {
    //freopen("in.txt", "r", stdin);
    init();
    cin >> T;
    while (T--) {
        cin >> n;
        cout << work() << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值