Codeforces 388 D. Fox and Perfect Sets

$ >Codeforces \space 388 D. ?Fox?and?Perfect?Sets<$

题目大意 :
定义一个完美的集合 \(S\) ,当且仅当 \(S\) 非负非空,且 \(\forall a, b \in S, a\text{ xor } b \in S\) ,求集合内最大元素不超过 \(n\) 的完美集合数量

\(1 \leq n \leq 10^9\)

解题思路 :

一个完美的集合等价于某个线性基能表示出的所有元素,所以问题转化为对能表示的最大元素 \(\leq n\) 的线性基计数

考虑一个集合的线性基可能有很多种,但是必然存在一种方案使得基上的二进制位表示出来的元素是最大元素,不妨直接对满足这种特征的线性基计数

考虑某一个二进制位如果在基中,那么基中其他位的数都不能有这个位,反之基中所有比它高的位都的数都可以有这个位

如果不考虑 \(n\) 的限制的话,可以得出一个简单的 \(dp[i][j]\) 表示从高到低第 \(i\) 个二进制位,已经选了 \(j\) 个二进制位作为基的方案数

根据上面推导可以得到 \(dp[i][j] = dp[i-1][j] \times 2^j + dp[i-1][j-1]\) (选这位为基/不选)

实际上如果有 \(n\) 的限制的话,是要满足有 \(1\) 的二进制位组成的二进制数不能超过 \(n\) ,可以直接套一个数位 \(dp\)

具体的说,\(dp[i][j][0/1]\) 表示从高到低第 \(i\) 个二进制位,已经选了 \(j\) 个二进制位作为基,当且有 \(1\) 的位是否是 \(n\) 在二进制下的前缀

根据当前 \(n\) 的二进制位是 \(0\) 还是 \(1\) 分讨转移即可

/*program by mangoyang*/
#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
    int f = 0, ch = 0; x = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    if(f) x = -x;
}

#define int ll
const int Mod = 1e9+7;
int s[55], f[55][55][2], len, ans;
inline void up(int &x, int y){ x = (x + y % Mod) % Mod; }
signed main(){
    int x; read(x); if(!x) s[++len] = 0;
    while(x) s[++len] = x % 2, x /= 2;
    reverse(s + 1, s + len + 1);
    f[0][0][1] = 1;
    for(int i = 1; i <= len; i++)
        for(int j = 0; j <= len; j++){
            if(j) up(f[i][j][0], f[i-1][j-1][0]);
            up(f[i][j][0], f[i-1][j][0] * (1ll << j));
            int x = (j ? (1ll << j - 1) : 1) % Mod;
            int y = (j ? (1ll << j - 1) : 0) % Mod;
            if(s[i] == 0) up(f[i][j][1], f[i-1][j][1] * x);
            else{
                if(j) up(f[i][j][1], f[i-1][j-1][1]);
                up(f[i][j][1], f[i-1][j][1] * y);
                up(f[i][j][0], f[i-1][j][1] * x);
            }
        }
    for(int i = 0; i <= len; i++)
        up(ans, f[len][i][0]), up(ans, f[len][i][1]);
    cout << ans;
    return 0;
}

原文地址:https://www.cnblogs.com/mangoyang/p/9709964.html

时间: 2024-07-31 05:33:28

Codeforces 388 D. Fox and Perfect Sets的相关文章

codeforces 388D Fox and Perfect Sets(线性基+数位dp)

#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define rep(i, a, b) for(int i=(a); i<(b); i++) #define sz(x) (int)x.size() #define de(x) cout<< #x<<" = &q

CodeForces 510 B. Fox And Two Dots(DFS 啊)

题目链接:http://codeforces.com/problemset/problem/510/B Fox Ciel is playing a mobile puzzle game called "Two Dots". The basic levels are played on a board of size n?×?m cells, like this: Each cell contains a dot that has some color. We will use diff

CodeForces 510 A. Fox And Snake(模拟啊 )

题目链接:http://codeforces.com/problemset/problem/510/A Fox Ciel starts to learn programming. The first task is drawing a fox! However, that turns out to be too hard for a beginner, so she decides to draw a snake instead. A snake is a pattern on a n by m

(CodeForces 510C) Fox And Names 拓扑排序

题目链接:http://codeforces.com/problemset/problem/510/C Fox Ciel is going to publish a paper on FOCS (Foxes Operated Computer Systems, pronounce: "Fox"). She heard a rumor: the authors list on the paper is always sorted in the lexicographical order.

网络流(最大流)CodeForces 512C:Fox And Dinner

Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). The i-th fox is ai years old. They will have dinner around some round tables. You want to distribute foxes such that: Each fox is sitting at some table

CodeForces Round #290 Fox And Dinner

而是Div2的最后一题,当时打比赛的时候还不会最大流.自己能够把它写出来然后1A还是很开心的. 题意: 有n个不小于2的整数,现在要把他们分成若干个圈.在每个圈中,数字的个数不少于3个,而且相邻的两个数之和是质数. 分析: 因为每个数都不小于2,所以相加得到的质数一定是奇数,那么在某个圈中,一定是奇偶相间的. 也就是 奇数相邻的两个数是偶数,偶数相邻的两个数是奇数. 所以一个圈中的数字一定是偶数个,所有的输入中也必须是偶数和奇数的个数相同才可能有解. 这转化为了二分图匹配,其中X是奇数,Y是偶数

Codeforces Round #277 (Div. 2)Valid Sets 树DP

题意:给出一棵树,并给出每个节点上的权值,求有多少个连通子块的最大值与最小值的差不超过d. 对于每个顶点建立一颗树,然后找比它价值大的   或者   价值相等且之前没有被当作顶点建立树的点,这样就避免重复了. dp[x]表示包涵x且以x为顶点的连通子树的个数,dp[x] = ∏ (dp[son[x]] + 1). 注意要用long long . #include<iostream> #include<iostream> #include<cstdio> #include

codeforces 510 C Fox And Names【拓扑排序】

题意:给出n串名字,表示字典序从小到大,求符合这样的字符串排列的字典序 先挨个地遍历字符串,遇到不相同的时候,加边,记录相应的入度 然后就是bfs的过程,如果某一点没有被访问过,且入度为0,则把它加入队列中,并将它指向的节点的入度减去1 另外如果len[i]<len[i-1],说明第i个字符串是i-1个字符串的前缀,但是它还排在后面,这样肯定不存在符合的字典序,直接输出“Impossible” 1 #include<iostream> 2 #include<cstdio> 3

寒假集训日志(五)——期中测验

10道题目,A了4道,5道会做,5道不会,果然渣渣... 这次测验感觉无限段错误..一个是初始化的问题,还一个建树的过程出错,但还不知道错在哪里.先附上几道没A的题, 以后慢慢解决. B - 拓扑 Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 510C Description Fox Ciel is going to p