码迷,mamicode.com
首页 > 其他好文 > 详细

18.10.17 考试总结

时间:2018-10-17 19:02:15      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:def   clu   通过   分享图片   using   div   ==   ros   const   

今天心态崩崩,,,.。

技术分享图片

   技术分享图片

这道题比较简单 因为每一位是单独对答案产生贡献的 所以枚举每一位 用数位dp求出该位是$1$的数量 在求出该位是$0$的

那么答案就是那一位对应的二的幂次再乘以$num1 * num0 * 2$ 每一对会产生两次贡献

代码

#include <bits/stdc++.h>
#define rg register
#define il inline
using namespace std;

typedef long long ll;
const ll MOD = 1e9 + 7;
int T, dig[40], lim;
ll p[50], dp[40][2][2], L, R, ans;

il ll read( ) {
    
    ll t = 1, ans = 0;
    char x; x = getchar( );
    while(x < 0 || x > 9) {
        if(x == -) t = -1;
        x = getchar( );
    }
    while(x >= 0 && x <= 9) {
        ans = ans * 10 + x - 0;
        x = getchar( );
    }
    return ans * t;
}

il void Init( ) {
    
    p[0] = 1;
    for(rg int i = 1;i <= 32;i ++) {
        p[i] = p[i - 1] * 2 % MOD;
    }
}

il void init(ll a) {
    
    ll b = a; lim = 0;
    while(b) {
        dig[++ lim] = b & 1;
        b >>= 1;
    }
}

il ll dfs(int dep, int up, ll ans, int pos) {
    
    if(dep == 0) return ans;
    if(~ dp[dep][up][ans]) return dp[dep][up][ans];
    int h = up ? dig[dep] : 1;
    ll tmp = 0;
    for(rg int i = 0;i <= h;i ++) {
        if((dep == pos) && (i == 1)) tmp += dfs(dep - 1, up && (i == h), ans + 1, pos);
        else tmp += dfs(dep - 1, up && (i == h), ans, pos); 
    }
    return dp[dep][up][ans] = tmp;
}

il ll solve(ll a, ll pos) {
    
    init(a); memset(dp, -1, sizeof(dp));
    return dfs(lim, 1, 0, pos);
}

il void Solve( ) {
    
    scanf("%d",& T);
    while(T --) {
        ll L, R, l;
        L = read( ), R = read( );
        l = L;
        if(L == 0) l = 1; ans = 0;
        for(rg int i = 0;i <= 31;i ++) {
            ll num1 = solve(R, i + 1) - solve(l - 1, i + 1);
            ll num0 = (R - L + 1 - num1) % MOD;
            ll num = 2 * num1 % MOD * num0 % MOD;
            ans = (ans + p[i] * num % MOD) % MOD;
        }
        printf("%lld\n", ans);
    }
}

int main( ) {

    freopen("xor.in","r",stdin);
    freopen("xor.out","w",stdout);
    Init( );    
    Solve( );
}

技术分享图片

 技术分享图片

这道题是一道博弈论的dp 现在用$dp[x][y][z]$数组表示三堆分别是$x,y,z$时他必输还是必胜

我们可以通过已经求出来的必败态来筛掉必败态 因为若是后继状态中有必败态 那么他就是必胜态 否则是必败态

若一个确定了一堆的状态为必败态 那么若剩下两堆的差值是固定的 它就可以通过加减到达我现在的状态 那么我现在状态就必胜

同样的 若我确定了两堆 那么另外一堆不管是什么都可以直接必胜

最后是三堆 若三堆确定了 那么它们两两差值也就确定了 同样可以确定我现在的状态

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 305;
int T, p[5];
bool dp[N][N][N], h[N][N][6];

void Solve( ) {
    
    scanf("%d",& T);
    for(int i = 0;i <= 300;i ++)
        for(int j = 0;j <= i;j ++) {
            for(int k = 0;k <= j;k ++) {
                bool tag = true;
                if(h[i][j - k][0]) tag = false;
                if(h[j][i - k][0]) tag = false;
                if(h[k][i - j][0]) tag = false;
                if(h[i][j][1])        tag = false;
                if(h[j][k][1])     tag = false;
                if(h[i][k][1])     tag = false;
                if(h[i - j][j - k][2]) tag = false;
                if(tag) {
                    dp[i][j][k] = true;
                    h[i][j - k][0] = h[j][i - k][0] = h[k][i - j][0] = h[i][j][1] = h[j][k][1] = h[i][k][1] = h[i - j][j - k][2] = true;
                }
            }
        }
}

int main( ) {
    
    freopen("stone.in","r",stdin);
    freopen("stone.out","w",stdout);
    Solve( );
    while(T --) {
        scanf("%d%d%d",& p[0],& p[1],& p[2]);
        sort(p, p + 3);
        if(dp[p[2]][p[1]][p[0]]) printf("No\n");
        else printf("Yes\n");
    }
}

技术分享图片

技术分享图片

这道题是一道恶星$dp$呕 这道题首先可以确定这玩意贪心取每一个值

然后$dp[i][j][k]$表示我到了第$i$个数 我总共分了$j$段当前状态是$0/1/2/3$时候的最优答案

状态是什么呢 我们考虑拆开绝对值 那么一段数$S$产生的贡献是他的两倍 不产生贡献 或者产生负二倍贡献 

所以贡献就是$2 0 0 -2$ 这种 并且不可能出现$2 0 0 0 2$这种 因为若他是$2$那么就需要负的去补 然后后面跟着一堆$0$也就是说最后两个盛了两个正的 所以末尾肯定是两个负的去补

状态$0$表示当前这个点在贡献为正的一段 $1$表示贡献为$0$的一段 并且这一段是跟在贡献为正的后面 $2/3$跟$1$正好相反

转移 $dp[i][j][0]$由 $dp[i - 1][j][0]/dp[i - 1][j - 1][2/3]$转移来 其余的类似 记住特判第一个和最后一个只产生$1 / -1$的贡献

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 30004;
int dp[N][205][5], a[N], n, k;

void Init( ) {
    
    scanf("%d%d",& n,& k);
    for(int i = 1;i <= n;i ++) scanf("%d",& a[i]);
}

void Solve( ) {
    
    memset(dp, 128, sizeof(dp));
    for(int i = 0;i <= n;i ++) dp[i][0][0] = dp[i][0][2] = 0;
    for(int i = 1;i <= n;i ++) {
        for(int j = 1;j <= min(i, k); j ++) {
            int flag = 2 - (j == 1 || j == k);
            dp[i][j][0] = max(dp[i - 1][j - 1][3], max(dp[i - 1][j][0], dp[i - 1][j - 1][2])) + flag * a[i];
            if(j > 1 && j < k) dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j][0]);
            dp[i][j][2] = max(dp[i - 1][j - 1][1], max(dp[i - 1][j][2], dp[i - 1][j - 1][0])) - flag * a[i];
            if(j > 1 && j < k) dp[i][j][3] = max(dp[i - 1][j][3], dp[i - 1][j - 1][2]);
        }
    }
    int ans = 0;
    for(int i = k;i <= n;i ++) ans = max(ans, max(dp[i][k][2], dp[i][k][0]));
    printf("%d\n", ans);
}

int main( ) {
    
    freopen("optimization.in","r",stdin);
    freopen("optimization.out","w",stdout);
    Init( );
    Solve( );
}

18.10.17 考试总结

标签:def   clu   通过   分享图片   using   div   ==   ros   const   

原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9806223.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!