uva 1489 - Math teacher's homework(数位dp)

题目链接:uva 1489 - Math teacher‘s homework

题目大意:给定n,k,以及序列m1,m2,…,mn,
要求找到一个长度为n的序列,满足0<=xi<=mi,
并且x1XORx2XOR…XORxn=k

解题思路:数位dp,在网上看了别人的代码,高大上。。。

假设有二进制数 k : 00001xxxx
mi:0001xxxxx,
那么对于xi即可以满足任意的x1XORx2XOR…XORxi?1XORxi+1XOR…XORxn,根据这一点进行数位dp。

dp[i][j]表示在第i个数,对于当前位是由j个1没有使用的。

特别对于dp[i][1] = dp[i][1] + dp[i-1][0], 因为dp[i-1][0]是没有1可以用的,即使不满足说随便添加数都是可以的,所以不能乘以bits。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;

const int maxn = 55;
const ll MOD = 1000000003LL;

ll N, K;
ll dp[maxn][maxn], num[maxn];

int main () {
    while (scanf("%lld%lld", &N, &K) == 2 && (N + K)) {
        ll ans = 0;
        for (int i = 1; i <= N; i++)
            scanf("%lld", &num[i]);

        int bit;
        for (bit = 30; bit >= 0; bit--) {
            memset(dp, 0, sizeof(dp));
            dp[0][0] = 1;

            ll cnt = 0, bits = (1<<bit);
            for (int i = 1; i <= N; i++) {

                if (num[i]&bits) {
                    cnt++;
                    for (int j = 0; j <= cnt; j++)
                        dp[i][j] = dp[i-1][j] * (num[i] - bits + 1) % MOD;
                    dp[i][1] = (dp[i][1] + dp[i-1][0]) % MOD;
                    for (int j = 2; j <= cnt; j++)
                        dp[i][j] = (dp[i-1][j-1] * bits + dp[i][j]) % MOD;

                    num[i] -= bits;
                } else {
                    for (int j = 0; j <= cnt; j++)
                        dp[i][j] = dp[i-1][j] * (num[i] + 1) % MOD;
                }
            }

            for (int i = 1; i <= cnt; i++)
                if ( ((cnt - i)&1) == ((K>>bit)&1) )
                    ans = (ans + dp[N][i]) % MOD;

            if ( (cnt&1) != ((K>>bit)&1) )
                break;
        }
        if (bit == -1)
            ans++;
        printf("%lld\n", ans);
    }
    return 0;
}

uva 1489 - Math teacher's homework(数位dp),布布扣,bubuko.com

uva 1489 - Math teacher's homework(数位dp)

时间: 2024-10-18 21:08:12

uva 1489 - Math teacher's homework(数位dp)的相关文章

HDU3693 Math Teacher&#39;s Homework

一句话题意: 给定$n, k以及m_1, m_2, m_3, ..., m_n$求$x_1 \oplus x_2 \oplus x_3 \oplus ... \oplus x_n == K$ 的方案数. 题解: 一开始口糊了一下,然后写代码的时候发现不少东西没考虑周到,于是就看起了题解. 我们首先需要发现一个重要的性质: 如果某一位上不受m限制(也就是选0或选1都可以)那么无论其它数的这一位位选什么都可以通过这一位来变成结果和K的这一位相等 为了避免来自$x <= m$的麻烦,我们首先让$m +

UVA 11361 - Investigating Div-Sum Property(数位DP)

题目链接:11361 - Investigating Div-Sum Property 白书上的例题,不过没有代码,正好前几天写了一题数位DP的题目,这题也就相对轻松了. dp[i][x][y]表示加到第i位,数字 % k,数位和 % k的组合情况数,那么现在要添加一个0 - 9的数字上去状态转移为 dp[i + 1][(x * 10 + num) % k][(y + num) % k],计算总和后,由于数字本身不能超过最大值,所以最后还要添加上恰好前几位都为最大值的情况.然后最后在判断一下该数

UVA - 11038 How Many O&#39;s? (数位dp)

How Many O's? 题意是求区间内数字中0的个数,比如100就有两个0. 数位dp吧,dp[i][j][k], i很明显表示当前位置,j表示找到的0的个数,k表示要找的0的个数.因为数字里0的个数最多32个,所以可以枚举32种k的情况,用数位dp去找. #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #

UVA 12063 Zeros and Ones (数位dp)

Binary numbers and their pattern of bits are always very interesting to computer programmers. In this problem you need to count the number of positive binary numbers that have the following properties: The numbers are exactly N bits wide and they hav

UVA 1397 - The Teacher&#39;s Side of Math(高斯消元)

UVA 1397 - The Teacher's Side of Math 题目链接 题意:给定一个x=a1/m+b1/n,求原方程组 思路:由于m*n最多20,所有最高项只有20,然后可以把每个此项拆分,之后得到n种不同无理数,每一项为0,就可以设系数为变元,构造方程进行高斯消元 一开始用longlong爆了,换成分数写法也爆了,又不想改高精度,最后是机智的用了double型过的,不过用double精度问题,所以高斯消元的姿势要正确,并且最后输出要注意-0的情况 代码: #include <c

uva 11361 Investigating Div-Sum Property 数位dp

// uva 11361 Investigating Div-Sum Property 数位dp // // 题目大意: // // 给你一个整数a和一个整数b,问在[a,b]范围内,有多少个自身被k整除并且 // 各位数之和也能被k整除.比如k = 7 ,322满足条件,因为332能被整除7,并 // 3 + 2 + 2 = 7 也能被7整除 // // 解题思路: // // 求一个区间的题目,这类题目,往往可以转化为不超过x的f(x).则最后要求 // 的就是f(b) - f(a-1).如

uva 417 - Word Index(数位dp)

题目连接:uva 417 - Word Index 题目大意:按照题目中的要求,为字符串编号,现在给出字符串,问说编号为多少,注意字符串必须为递增的,否则编号为0. 解题思路:其实就是算说比给定字符串小并且满足递增的串由多少个.dp[i][j]表示第i个位为j满足比给定字符串小并且满足递增的串. dp[i][j]=∑k=0j?1dp[i?1][k]. 注意每次要处理边界的情况,并且最后要加上自身串.并且在处理边界的时候dp[i][0]要被赋值为1,代表前i个为空的情况. #include <cs

UVA 1397 - The Teacher&amp;#39;s Side of Math(高斯消元)

UVA 1397 - The Teacher's Side of Math 题目链接 题意:给定一个x=a1/m+b1/n.求原方程组 思路:因为m*n最多20,全部最高项仅仅有20.然后能够把每一个此项拆分.之后得到n种不同无理数,每一项为0.就能够设系数为变元.构造方程进行高斯消元 一開始用longlong爆了.换成分数写法也爆了,又不想改高精度.最后是机智的用了double型过的,只是用double精度问题,所以高斯消元的姿势要正确,而且最后输出要注意-0的情况 代码: #include

uva 10712 - Count the Numbers(数位dp)

题目链接:uva 10712 - Count the Numbers 题目大意:给出n,a,b:问说在a到b之间有多少个n. 解题思路:数位dp,dp[i][j][x][y]表示第i位为j的时候,x是否前面是相等的,y是否已经出现过n.对于n=0的情况要特殊处理前导0,写的非常乱,搓死. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using na