abc246(D-F)

D:

枚举a,二分b,更新最小值

code:


void solve(int Case) {
    int n;
    int x;
    cin >> n;
    int ans = 2e18;
    auto check = [&](int a, int b) {
        int x = a * a * a + a * a * b + a * b * b + b * b * b;
        if (x < 0) return true;
        return x - n >= 0;
    };
    auto cal = [](int a, int b) {
        int x = a * a * a + a * a * b + a * b * b + b * b * b;
        return x;
    };
    for (x = 0; x * x * x <= n; x++);
    for (int i = 0; i <= x; i++) {
        int l = 0, r = 1e6;
        while (l < r) {
            int mid = l + r >> 1;
            if (check(i,mid)) r = mid;
            else l = mid + 1;
        }
        ans = min(cal(i, r), ans);
    }
    cout << ans << nline;
}

E


大致题意是从a到b每次都可以选择一条斜着的直线走,问a到b的最短距离
从一个点每次都有n种选择,显然时间复杂度过高,可以考虑每次更换方向算作一次操作边权做1,不更换方向边权为0,所以需要再扩展一维存储扩展到这个点时的方向

code:


const int N = 2010;
char s[N][N];
int dist[N][N][5];
int vis[N][N][5];
int n;
struct T {
    int x, y, w, d;
};
int ax, ay, bx, by;
int dx[4] = {1, 1, -1, -1}, dy [4] = {1, -1, 1, -1};
void bfs(int x, int y) {
    deque<T> q;
    for (int i = 0; i < 4; i++) {
        int tx = x + dx[i], ty = y + dy[i];
        if (tx >= 1 and ty >= 1 and tx <= n and ty <= n) {
            if (s[tx][ty] == '#') continue;
            q.push_front({x, y, 1, i});
        }
    }
    memset(dist, 0x3f, sizeof dist);
    while (q.size()) {
        auto [x, y, w, d] = q.front();
        q.pop_front();
        if (vis[x][y][d]) continue;
        vis[x][y][d] = true;
        for (int i = 0; i < 4; i++) {
            int tx = x + dx[i], ty = y + dy[i];
            if (tx >= 1 and ty >= 1 and tx <= n and ty <= n) {
                if (s[tx][ty] == '#') continue;
                int nw = (d != i);
                if (dist[tx][ty][i] > w + nw) {
                    dist[tx][ty][i] = w + nw;
                    if (nw) {
                        q.push_back({tx, ty, w + nw, i});
                    } else {
                        q.push_front({tx, ty, w + nw, i});
                    }
                }
            }
        }
    }
    int res = 1e18;
    for (int i = 0; i < 4; i++) {
        res = min(res, dist[bx][by][i]);
    }
    if (res == 0x3f3f3f3f3f3f3f3f or res == 1e18) res = -1;
    cout << res << nline;

}
void solve(int Case) {

    cin >> n;
    cin >> ax >> ay >> bx >> by;
    for (int i = 1; i <= n; i++) {
        cin >> (s[i] + 1);
    }
    bfs(ax, ay);
}

F:

每个字符集可以扩展的有\(s[i]^{l}\),然后按照容斥原理减去相同的部分

code:

int qmi(int a, int b, int p) {
    int res = 1 % p;
    while (b) {
        if (b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
void solve(int Case) {
    int n, l;
    cin >> n >> l;
    int res=0;
    vector<string> s(n);
    for (auto &i : s) {
        cin >> i;
       
    }
    for (int i = 1; i < 1 << n; i++) {
        int cnt = 0;
        vector<int> v(26);
        for (int j = 0; j < n; j++) {
            if (i >> j & 1) {
                for (auto it : s[j]) {
                    v[it-'a']++;
                }
            }
            cnt += (i >> j & 1);
        }
        int sum = 0;
        for (auto j : v) if (j == cnt) sum++;
        sum = qmi(sum, l, mod);
        if (cnt & 1) {
            res += sum;
            res %= mod;
        } else {
            res -= sum;
            res = (res % mod + mod) % mod;
        }
    }

    cout << res%mod << nline;
}
posted @ 2022-04-03 20:35  指引盗寇入太行  阅读(107)  评论(0编辑  收藏  举报