2016多校第六场,HDU5793,5794,5795,5798,5800,5802,5803

这场状态不对劲,打的很差,该出的题都没看(莫名卡水题),sb博弈的表也能打错。A题打表也用太久时间,自己的板子都是错的(全世界找板子),还被题目吓住(钦定看不懂就是神题)。队内合作方式有点问题。

HDU5793

这是个打表很快就能发现等比性质的题。但是赛上我写了个矩阵快速幂(真不知道当时怎么想的)。。。

这个题就递推比较劲,此处解释下。

要求 0k1,k2,...,kmn1j<mCkjkj+1% 1000000007

很显然必须满足 0k1k2...kmn 才对答案有贡献,其他情况都是0。

0k1k2...kmn1j<mCkjkj+1% 1000000007

0kmn(0km1kmCkm1km(...0k1k2Ck1k2))

0kmn(0km1kmCkm1km(...0k2k3Ck2k32k2))

上面 0k2k3Ck2k32k2 由二项式 (2+1)k3 展开得到

一步一步合并回去就是 0kmnmkm 等比数列遍得到了。

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

ll Pow(ll a, ll n) {
    ll ret = 1;
    a %= MOD;
    while(n) {
        if(n & 1) ret = ret * a % MOD;
        a = a * a % MOD;
        n >>= 1;
    }
    return ret;
}
int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int T;
    scanf("%d", &T);
    ll n, m;
    while(T--) {
        scanf("%lld%lld", &n, &m);
        ll ans = Pow(m, n+1) - 1;
        ans = (ans + MOD) % MOD;
        ans = ans * Pow(m - 1, MOD - 2) % MOD;
        printf("%lld\n", ans);
    }

    return 0;
}

HDU5794

n(n1e18)m(m1e18) 的格子有 r 个坏点,问你有多少种方案像马一样从 (1,1) 跳到 (n,m) 。每次横坐标和纵坐标只能递增。

这题可以先想想数据范围小的时候我们怎么搞。就是一种像组合数的 dp 。打个表可以发现,整个图有值的地方是斜着的杨辉三角,可以通过坐标计算出当前点 (x,y) 对应的杨辉三角的位置,然后用 lucas 定理算组合数,再去重。用容斥去重,考虑 ans[i] 最后走到的坏点是 i ,从 i 到终点的方案数。对坐标的点进行排序,倒着遍历坏点,比 i 大的点都是求出来了的。那么从 i 出发到终点的且不经过其他任何坏点的方案数就等于直接从 i 出发到终点的方案数减去在 i 之后的点 j 到终点的方案数乘 ij 的方案数,即减去 ans[j]calc(i>j) 。最后算出从起点到终点的方案数,枚举坏点,减去以每个坏点结尾的方案数就是最后答案。注意!不能以0判断当前点是否有用!!!因为 mod 很小,大数据可以使得方案数 %mod 为0

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
#define fi first
#define se second
using namespace std;
const int inf = 0x3f3f3f3f;
const ll MOD = 110119;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

ll F[MOD + 10];
void init(ll p) {
    F[0] = 1;
    for(ll i = 1; i <= p; i++) {
        F[i] = F[i-1] * i % MOD;
    }
}
ll inv(ll a, ll m) {
    if(a == 1) return 1;
    return inv(m % a, m) * (m - m / a) % m;
}
ll lucas(ll n, ll m, ll p) {
    ll ans = 1;
    while(n && m) {
        ll a = n % p;
        ll b = m % p;
        if(a < b) return 0;
        ans = ans * F[a] % p * inv(F[b] * F[a-b] % p, p) % p;
        n /= p;
        m /= p;
    }
    return ans;
}
typedef pair  sta;
sta get(ll n, ll m) {
    sta tmp;
    tmp.fi = (n + m + 1) / 3 - 1;
    tmp.se = m - tmp.fi - 1;
    return tmp;
}

ll calc(ll n, ll m) {
    if((n + m + 1) % 3) return 0;
    sta ret = get(n, m);
    // cout << ret.fi << ' ' << ret.se << endl;
    if(ret.se < 0 || ret.se > ret.fi) return 0;
    return lucas(ret.fi, ret.se, MOD);
}
ll ans[maxv];


int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    ll n, m, r;
    init(MOD);
    int cas = 0;
    while(scanf("%lld%lld%lld", &n, &m, &r) != EOF) {
        std::vector pos;
        printf("Case #%d: ", ++cas);
        for(int i = 0; i < r; i++) {
            ll x, y;
            scanf("%lld%lld", &x, &y);
            if(calc(x, y) < 0) continue;
            pos.push_back(sta(x, y));
        }
        sort(ALL(pos));
        ll res = calc(n, m);
        for(int i = pos.size() - 1; ~i; i--) {
            ans[i] = calc(n-pos[i].fi+1, m-pos[i].se+1);
            for(int j = i + 1; j < pos.size(); j++) {
                if(pos[j].se < pos[i].se) continue;
                ans[i] = (ans[i] - ans[j] * calc(pos[j].fi-pos[i].fi+1, pos[j].se-pos[i].se+1) % MOD + MOD) % MOD;
            }
            res = (res - ans[i] * calc(pos[i].fi, pos[i].se) % MOD + MOD) % MOD;
        }
        printf("%lld\n", res);
    }

    return 0;
}

HDU5795

打表可以很容易的发现 %8 的规律

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int T;
    scanf("%d", &T);
    while(T--) {
        int n;
        scanf("%d", &n);
        int ans = 0;
        for(int i = 1; i <= n; i++) {
            int x;
            scanf("%d", &x);
            if(x % 8 == 0) {
                x--;
            }
            else if((x + 1) % 8 == 0) {
                x++;
            }
            ans ^= x;
        }
        if(ans) puts("First player wins.");
        else puts("Second player wins.");
    }

    return 0;
}

HDU5798

这题很劲。

看到 xor 第一反应就是拆位来做。因为有 abs ,根本无法统一处理,不统一一定超时,因此必须拆开。考虑某位 cur 对于答案的贡献,若前一个与后一个数此位相同,那么无论是否异或,答案都是不改变。再仔细想想只有两个数的情况,设最高不同位为 hig (全同为0)设大的数为 a 小的数为 b ,那么比 hig 位小的位 j 对答案的贡献都是 a j 位减去 b j 位,当然若我们这位被异或了,那么更小的 j 位贡献全部反掉。当然,若 j 位也被异或了,那么又翻转了回来。因此只需要看到底此位被异或多少次就行了。推广到多个数的情况就行了。

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

ll arr[22][22];
int dep;
ll ansl, ansr;
int digit[22];
void dfs(int pos, ll sum) {
    if(pos == dep) {
        ll res = 0;
        for(int i = 0; i < pos; i++) {
            res |= digit[i] << i;
        }
        if(sum < ansr) {
            ansr = sum;
            ansl = res;
        }
        else if(sum == ansr) ansl = min(ansl, res);
        return;
    }
    for(digit[pos] = 0; digit[pos] < 2; digit[pos]++) {
        ll nsum = sum + arr[pos][pos];
        for(int j = 0; j < pos; j++) {
            if(digit[j] ^ digit[pos]) nsum -= arr[pos][j];
            else nsum += arr[pos][j];
        }
        dfs(pos + 1, nsum);
    }
}
int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int T;
    scanf("%d", &T);
    while(T--) {
        CLR(arr);
        int n;
        scanf("%d", &n);
        int x; scanf("%d", &x);
        for(int i = 1; i < n; i++) {
            int y;
            scanf("%d", &y);
            int hig = 19;
            while(hig >= 0 && ~(x ^ y) >> hig & 1) hig--;
            int big = max(x, y);
            int small = min(x, y);
            for(int j = hig; ~j; j--) {
                arr[hig][j] += (big >> j & 1) - (small >> j & 1);
            }
            swap(x, y);
        }
        dep = 20;
        while(dep > 0 && !arr[dep-1][dep-1]) dep--;
        for(int i = 0; i <= dep; i++) {
            for(int j = 0; j <= i; j++) {
                arr[i][j] <<= j;
            }
        }
        ansl = ansr = inf;
        dfs(0, 0);
        printf("%lld %lld\n", ansl, ansr);
    }

    return 0;
}

HDU 5780

水dp

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

int a[maxv];
ll dp[2][maxv][3][3];
int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int T;
    scanf("%d", &T);
    while(T--) {
        int n, s;
        scanf("%d%d", &n, &s);
        CLR(dp);
        for(int i = 1; i <= n; i++) scanf("%d", a + i);
        dp[0][0][0][0] = 1;
        int cur = 0;
        for(int i = 1; i <= n; i++) {
            cur ^= 1;
            for(int j = 0; j <= s; j++) 
            for(int k = 0; k <= 2; k++) 
            for(int l = 0; l <= 2; l++) {
                dp[cur][j][k][l] = 0;
                if(j >= a[i]) {
                    dp[cur][j][k][l] += dp[cur^1][j-a[i]][k][l];
                    if(k) dp[cur][j][k][l] += dp[cur^1][j-a[i]][k-1][l];
                }
                if(l) dp[cur][j][k][l] += dp[cur^1][j][k][l-1];
                dp[cur][j][k][l] += dp[cur^1][j][k][l];
                // printf("dp[%d][%d][%d][%d] = %lld\n", i, j, k, l, dp[i][j][k][l]);
                dp[cur][j][k][l] %= MOD;
            }
        }

        ll ans = 0;
        for(int i = 1; i <= s; i++) {
            ans += dp[cur][i][2][2];
            ans %= MOD;
        }
        printf("%lld\n", ans * 4 % MOD);
    }
    return 0;
}

HDU 5802

贪心,注意停顿和加取个max

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int T;
    scanf("%d", &T);
    while(T--) {
        int p, q;
        scanf("%d%d", &p, &q);
        if(p <= q) {
            printf("%d\n", q - p);
            continue;
        }
        p -= q;
        // cout << p << endl;
        // cout << 32 - __builtin_clz(p) << endl;
        int ans = inf;
        int pause = 0;
        int cur = 0;
        while(p) {
            if(p == 1) {
                ans = min(ans, cur + pause + 1);
                break;
            }
            int big = 32 - __builtin_clz(p);
            int num = 1 << big;
            num--;
            // printf("num = %d\n", num);
            ans = min(ans, cur + __builtin_popcount(num) + max(pause, min(q, num - p)));
            pause++;
            num >>= 1;
            p -= num;
            cur += __builtin_popcount(num);
        }
        printf("%d\n", ans);
    }

    return 0;
}

HDU5803

数位 dp ,很不错的学习题。。

//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;


ll p[4];
int dp[66][20][5][5];
int val[3] = {-2, 0, 2};
inline int get(int num, int sub) {
    if(num > 2) return 3;
    sub += val[num];
    if(abs(sub) <= 1) return sub + 1;
    return sub > 0 ? 3 : -1;
}
int dfs(int pos, int mark, int first, int second) {
    if(pos == -1) return first >= 2 && second >= 1;
    int &ret = dp[pos][mark][first][second];
    if(-1 != ret) return ret;
    ret = 0;
    int digit[4];
    for(int i = 0; i < 4; i++) digit[i] = (mark >> i & 1) ? 1 : (p[i] >> pos & 1);
    for(int i = 0; i <= digit[0]; i++) {
        for(int j = 0; j <= digit[1]; j++) {
            for(int k = 0; k <= digit[2]; k++) {
                for(int l = 0; l <= digit[3]; l++) {
                    int newfirst = get(first, i + k - j - l);
                    int newsecond = get(second, i + l - j - k);
                    if(-1 == newfirst || -1 == newsecond) continue;
                    int newmark = mark;
                    if(i < digit[0]) newmark |= 1;
                    if(j < digit[1]) newmark |= 2;
                    if(k < digit[2]) newmark |= 4;
                    if(l < digit[3]) newmark |= 8;
                    ret = (ret + dfs(pos-1, newmark, newfirst, newsecond)) % MOD;
                }
            }
        }
    }
    return ret;
}
int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int T;
    scanf("%d", &T);
    while(T--) {
        memset(dp, -1, sizeof dp);
        for(int i = 0; i < 4; i++)
            scanf("%lld", p + i);
        printf("%d\n", dfs(61, 0, 1, 1));
    }

    return 0;
}

你可能感兴趣的:(杂题)