BestCoder Round #40 A B C

A,水题,直接枚举到sqrt

B,每次对于每一位枚举,如果小于当前位,那么答案可以计算出来,增加得答案为:设3个部分,前完全一样的部分a,中间新选的一个b,后面的全排列c,这样就把每部分和每两部分能够组成的逆序对个数计算出来,由于n只有100,里面在去枚举也是没问题的,主要是后面全排列c的逆序对数,这个可以利用dp处理出来,dp[i] = dp[i - 1] * i + i! * sum(i - 1),sum(i)表示1到i的和。

C:推公式,C(n, m) = C(n - 1, m - 1) + C(n - 1, m) = C(n - 1, m - 1) + C(n - 2, m - 1) + C(n - 2, m)....这样对于C(i, k),a <= i <= b的和,就等于是C(b + 1, k + 1) - C(a, k + 1),然后由于p比较小,要用lucas计算组合数即可

代码:

A:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int t, n;

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        int ans = 2000000000LL;
        for (int i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                ans = min(ans, (n / i + i) * 2);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

B:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
const int N = 105;
const int MOD = 1000000007;

int n, a[N], vis[N], dp[N], fac[N], sum[N];

int tot;

int dfs(int u) {
    if (u == n) return 0;
    int ans = 0;
    int cnt = 0;
    for (int i = 1; i < a[u]; i++) {
        if (vis[i]) continue;
        ans = (ans + (ll)tot * fac[n - u - 1] % MOD) % MOD;
        if (n - u - 1 > 0) ans = (ans + (ll)cnt * (n - u - 1) % MOD * fac[n - u - 2] % MOD) % MOD;
        ans = (ans + dp[n - u - 1]) % MOD;
        int tmp = 0;
        for (int j = u - 1; j >= 0; j--) {
            if (a[j] > i) tmp++;
        }
        int sb = 0;
        int sbb = 0;
        for (int j = 1; j <= n; j++) {
            if (j == i) continue;
            if (vis[j]) sbb += sb;
            else sb++;
        }
        if (n - u - 1 > 0) ans = (ans + (ll)sbb * (n - u - 1) % MOD * fac[n - u - 2] % MOD) % MOD;
        ans = (ans + (ll)tmp * fac[n - u - 1] % MOD) % MOD;
        cnt++;
    }
    vis[a[u]] = 1;
    for (int i = a[u] + 1; i <= n; i++) if (vis[i]) tot++;
    ans = (ans + dfs(u + 1)) % MOD;
    return ans;
}

int main() {
    fac[0] = 1;
    for (int i = 1; i < N; i++) {
        fac[i] = (ll)fac[i - 1] * i % MOD;
        sum[i] = (sum[i - 1] + i) % MOD;
    }
    for (int i = 2; i < N; i++)
        dp[i] = ((ll)dp[i - 1] * i % MOD + (ll)fac[i - 1] * sum[i - 1] % MOD) % MOD;
    while (~scanf("%d", &n)) {
        for (int i = 0; i < n; i++) scanf("%d", &a[i]);
        memset(vis, 0, sizeof(vis));
        tot = 0;
        printf("%d\n", dfs(0));
    }
    return 0;
}


C:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100005;
typedef long long ll;

int f[N], f2[N];
int x1, x2, y1, y2, p;

int pow_mod(int x, int k) {
    int ans = 1;
    while (k) {
        if (k&1) ans = (ll)ans * x % p;
        x = (ll)x * x % p;
        k >>= 1;
    }
    return ans;
}

int C(int n, int m) {
    if (m > n || n < 0 || m < 0) return 0;
    return (ll)f[n] * f2[m] % p * f2[n - m] % p;
}

int lucas(int n, int m) {
    if (m == 0) return 1;
    return (ll)C(n % p, m % p) * lucas(n / p, m / p) % p;
}

int main(){
    while (~scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &p)) {
        f[0] = 1;
        for (int i = 1; i < min(N, p); i++)
            f[i] = (ll)f[i - 1] * i % p;
        f2[min(N, p) - 1] = pow_mod(f[min(N, p) - 1], p - 2);
        for (int i = min(N, p) - 2; i >= 0; i--)
            f2[i] = (ll)f2[i + 1] * (i + 1) % p;
        int ans = 0;
        for (int i = y1; i <= y2; i++) ans = (ans + ((lucas(x2 + 1, i + 1) - lucas(x1, i + 1)) % p + p) % p) % p;
        printf("%d\n", ans);
    }
     return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值