18.10.17 考试总结

今天心态崩崩,,,.。

这道题比较简单 因为每一位是单独对答案产生贡献的 所以枚举每一位 用数位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( );
}

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

时间: 2024-10-08 07:17:22

18.10.17 考试总结的相关文章

18.8.17 考试总结

高斯消元[问题描述]everlasting 觉得太无聊了,于是决定自己玩游戏! 他拿出了n 个小圆,第i 个的颜色是ai.接着他将这n 个小圆复制m 次并依次连接起来. 之后他发现其中有很多颜色相同的小圆,于是他决定:每有k 个连续颜色相同的小圆就将他们消去, 并将剩下的依次连接.(注意只会消除k个,即使有超过k 个)他将每次从头开始不断进行这个操作直到无法操作为止. 他想知道最后能剩下多少个小圆? [输入格式] 从文件guass.in 中输入数据. 第一行三个正整数n,m,k,表示开始小圆的个

18.10.22 考试总结

我真的我要被我自己给猪死了md T1让输出边长我输出面积硬生生掉了100分 气死 这道题我之前在讲单调栈的时候是讲过的 对于每一个位置 维护一个他的$up$表示以这里为起点只走$1$向上走的高度 然后对于每一行都跑一边求最大矩形的单调栈即可 维护一个单增的 每次弹栈的时候求出以弹栈元素为矩形边长的最大矩形面积 不过这道题是求最大正方形 就改成边长取$min$再取$max$即可 代码 #include <bits/stdc++.h> #define il inline #define rg re

18.10.4 考试总结

这道题就是一道肥!肠!裸!的!轮廓线dp 然后因为细节太多了还因为有一个sbsbsb编译错误 就是不准我函数名字取count...我恨 我永远讨厌轮廓线dp 代码 #include <bits/stdc++.h> using namespace std; const int N = 1e6 + 5; int dp[2][N],n,m,len[200],cnt[N],ans; char s[200][40]; void Init( ) { scanf("%d%d",&

18.10.6 考试总结

这道题就是一道模拟题 也没有什么细节 反正蛮好写的 代码 #include <bits/stdc++.h> using namespace std; const int N = 1005; int hx, hy, lx, ly, now, ma, h; int vis[2 * N][2 * N], T; char opt[105]; void deal(int sta, char opt, int del) { if(sta == 1) { if(opt == 'E' || opt == 'W

10.15 iptables filter表案例 10.16/10.17/10.18 iptables nat表应用

10.15 iptables filter表案例 10.16/10.17/10.18 iptables nat表应用 扩展 iptables应用在一个网段 http://www.aminglinux.com/bbs/thread-177-1-1.html sant,dnat,masquerade http://www.aminglinux.com/bbs/thread-7255-1-1.html iptables限制syn速率 http://www.aminglinux.com/bbs/thre

10.15 iptables filter表案例 10.16/10.17/10.18 iptable

七周四次课 10.15 iptables filter表案例 10.16/10.17/10.18 iptables nat表应用 10.15 iptables filter表案例 10.16/10.17/10.18 iptables nat表应用 打开端口转发, 调整内核参数 增加一条规则 所添加的规则 B机器设置默认网关 设置公共DNS C设备与A通信,通过端口转换的形式,将原有iptables清空 上面为进来的包进行转换,下面为出去的包进行转换 原文地址:http://blog.51cto.

18.9.17 poj2492 A Bug&#39;s Life

描述 BackgroundProfessor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their

18/10/05-5-BugKu-逆向-LittleRotatorGame(NJCTF)

0x00 题目链接:https://pan.baidu.com/s/1FLIaSN6EOe34qQNO_8yi-g 提取码:phou 0x01 native层分析 根据提示程序用了O-LLVM混淆,IDA分析ANativeActivity_onCreate函数,分析此处 1 v24 = flg((int)v67, &v89); 2 j___android_log_print(4, "an-activity", "The flag is:njctf{%s}",

[CareerCup] 18.10 Word Transform 单词转换

18.10 Given two words of equal length that are in a dictionary, write a method to transform one word into another word by changing only one letter at a time. The new word you get in each step must be in the dictionary. 这道题让我们将一个单词转换成另一个单词,每次只能改变一个字母,