省选测试6

A Colorado Potato Beetle

题目大意 : 求路径包起来的面积

  • 数据范围太大,就把一个点的周围9个点一起离散化,然后BFS就好了

Code

Show Code
#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 1e3 + 5;

int read(int x = 0, int f = 1, char c = getchar()) {
    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-') f = -1;
    for (; c >='0' && c <='9'; c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

struct Node {
    int lx, ly, rx, ry;
}a[N];

long long ans;
bool v[N*3][N*3];
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0}; 
int n, bx[N*3], by[N*3], mx, my, qx[N*N*9], qy[N*N*9];

void Add(int x, int y) {
    bx[++mx] = x - 1; bx[++mx] = x; bx[++mx] = x + 1;
    by[++my] = y - 1; by[++my] = y; by[++my] = y + 1;
}

int main() {
    n = read();
    bx[++mx] = -1e9 - 1; bx[++mx] = 1e9 + 1; bx[++mx] = 1e9 + 2;
    by[++my] = -1e9 - 1; by[++my] = 1e9 + 1; by[++my] = 1e9 + 2;
    int x = 0, y = 0; Add(0, 0);
    for (int i = 1; i <= n; ++i) {
        char od; scanf(" %c", &od); int l = read();
        a[i].lx = x, a[i].ly = y;
        od == 'U' ? x -= l : od == 'D' ? x += l : od == 'L' ? y -= l : y += l;
        a[i].rx = x, a[i].ry = y;
        Add(x, y);
    }
    sort(bx + 1, bx + mx + 1);
    sort(by + 1, by + my + 1);
    mx = unique(bx + 1, bx + mx + 1) - bx - 1;
    my = unique(by + 1, by + my + 1) - by - 1;
    for (int k = 1; k <= n; ++k) {
        int lx = lower_bound(bx + 1, bx + mx + 1, a[k].lx) - bx;
        int ly = lower_bound(by + 1, by + my + 1, a[k].ly) - by;
        int rx = lower_bound(bx + 1, bx + mx + 1, a[k].rx) - bx;
        int ry = lower_bound(by + 1, by + my + 1, a[k].ry) - by;
        if (lx > rx || ly > ry) swap(lx, rx), swap(ly, ry);
        for (int i = lx; i <= rx; ++i)
            for (int j = ly; j <= ry; ++j)
                v[i][j] = 1;
    }
    int l = 1, r = 1; qx[1] = qy[1] = 1; v[1][1] = 1;
    ans = 1ll * ((int)2e9 + 3) * ((int)2e9 + 3);
    while (l <= r) {
        int x = qx[l], y = qy[l]; l++; 
        ans -= 1ll * (bx[x+1] - bx[x]) * (by[y+1] - by[y]);
        for (int k = 0; k < 4; ++k) {
            int tx = x + dx[k], ty = y + dy[k];
            if (tx <= 0 || tx >= mx || ty <= 0 || ty >= my || v[tx][ty]) continue;
            r++; qx[r] = tx; qy[r] = ty; v[tx][ty] = 1;
        }
    }
    printf("%lld
", ans);
    return 0;
}

B Distinct Paths

题目大意 : nm的木板涂色,满足从左上角只能向下和向右到右下角的任意一条路径上不会出现相同的颜色

  • 数据范围比较小,直接暴搜剪枝就能过了

Code

Show Code
#include <cstdio>

using namespace std;
const int N = 15, M = 1e9 + 7;

int read(int x = 0, int f = 1, char c = getchar()) {
    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-') f = -1;
    for (; c >='0' && c <='9'; c = getchar())
        x = x * 10 + c - '0';
    return x * f;
}

int n, m, k, a[N][N], b[N], f[N][N];

int Cal(int s, int ans = 0) {
    for (; s; s -= s & -s) ans++;
    return ans;
}

int Dfs(int x, int y) {
    y == m ? x++, y = 1 : y++;
    if (x > n) return 1;
    int s = f[x-1][y] | f[x][y-1], tmp = -1, ans = 0;
    if (k - Cal(s) < n - x + m - y + 1) return 0;
    for (int i = 1; i <= k; ++i) {
        if ((s & 1 << i - 1) || (a[x][y] && a[x][y] != i)) continue;
        f[x][y] = s | (1 << i - 1);
        if (!b[i]++) ans = (ans + (tmp == -1 ? tmp = Dfs(x, y) : tmp)) % M;
        else ans = (ans + Dfs(x, y)) % M;
        b[i]--;
    }
    return ans;
}

int main() {
    n = read(), m = read(), k = read();
    if (n + m - 1 > k) return puts("0"), 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            a[i][j] = read(), b[a[i][j]]++;
    printf("%d
", Dfs(1, 0));
    return 0;
}

C 不好不坏题

题目大意 : 找1e10范围内约数和 % K 为 0 的数的和

  • 1e8的数据点卡内存,线性筛过不了 T-T

  • 对于 K=2 的情况打表就很容易发现所有平方数的2的次方倍的约数和都是与0不同余的,数量是根号级别的,枚举就行,所以算出所有的数的和然后减去这些数的和

  • 对于 K=2017 的情况就有点麻烦。由于约数和是 (d(i)) 是积性函数,所以只要找到 (d(i)equiv 0mod k) 的 i,那么如果有与 i 互质的数 j, (d(ij)equiv 0mod k),然后如果能找到只有一个质因子且满足条件的 i,那么就可以O(1)求出一个数所有倍数之和。判断质数的时候用miller_rabin

Code

Show Code
#include <cmath>
#include <cstdio>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 3e5 + 5, M = 1e9 + 7, inv2 = 500000004;

ll n;
bool v[N];
int p, ans, pri[N], tot, a[N], cnt;

void Init(int n) {
    v[1] = 1;
    for (int i = 2; i <= n; ++i) {
        if (!v[i]) pri[++tot] = i;
        for (int j = 1; j <= tot && i * pri[j] <= n; ++j) {
            v[i*pri[j]] = 1;
            if (i % pri[j] == 0) break;
        }
    }
}

ll Mul(ll a, ll b, ll M) {
    return ((ull)a * b - (ull)((long double)a * b / M) * M + M) % M;
}

ll Pow(ll a, ll k, ll M, ll ans = 1) {
    for (; k; k >>= 1, a = Mul(a, a, M))
        if (k & 1) ans = Mul(ans, a, M);
    return ans;
}

bool Judge(ll x) {
    if (x < N) return !v[x];
    for (int i = 1; i <= 9; ++i)
        if (x % pri[i] == 0) return x == pri[i];
    for (int i = 1; i <= 2; ++i) {
        if (x == pri[i]) return 1;
        ll k = x - 1, p = Pow(pri[i], k, x);
        if (p != 1) return 0;
        while (p == 1 && k % 2 == 0) {
            p = Pow(pri[i], k >>= 1, x);
            if (p != 1 && p != x - 1) return 0;
        }
    }
    return 1;
}

int Cal(ll x) {
    ll k = n / x;
    return (k + 1) % M * (k % M) % M * inv2 % M * (x % M) % M;
}

int main() {
    scanf("%lld%d", &n, &p);
    if (p == 2) {
        ans = (n + 1) % M * (n % M) % M * inv2 % M;
        ll tmp;
        for (int i = 1; (tmp = 1ll * i * i) <= n; ++i) {
            if ((ans -= tmp % M) < 0) ans += M;
            if (tmp * 2 <= n && (ans -= tmp * 2 % M) < 0) ans += M;
        }
        printf("%d
", ans);
    }
    else {
        Init(min(n, (ll)N - 1));// k == 1
        for (ll i = 4033; i <= n; i += 4034)
            if (Judge(i)) ans = (ans + Cal(i)) % M, a[++cnt] = i;
        ll tmp;
        for (int i = 1, lim = n / 12101; i <= cnt && a[i] <= lim; ++i)
            for (int j = 1; j <= i && (tmp = 1ll * a[i] * a[j]) <= n; ++j)
                ans = (ans - Cal(tmp) + M) % M;
        int sq = sqrt(n); // k == 2;
        for (int i = 1; i <= sq; ++i)
            if (Judge(i) && (1ll * i * i + i + 1) % 2017 == 0)
                ans = (ans + Cal(1ll * i * i)) % M;
        tmp = 229 * 229 * 229;// k == 3
        ans = (1ll * ans + Cal(tmp) - Cal(229ll * tmp) + M) % M;
        printf("%d
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shawk/p/14375077.html