zoukankan      html  css  js  c++  java
  • BZOJ CF388D. Fox and Perfect Sets [线性基 数位DP]

    CF388D. Fox and Perfect Sets

    题意:求最大元素(le n)的线性空间的个数


    给神题跪了 orz


    容易想到 每个线性基对应唯一的线性空间,我们可以统计满足条件的对应空间不同的线性基个数

    每一位我们插入一个向量,就获得了这一位的控制权,否则这一位是自由的

    因为要(le n),可以使用数位DP

    从高位到低位考虑,设当前第i位,已经插入了j个向量

    没有天际线的限制

    • 插入向量i的话,之前的向量位i必须是0,1种情况
    • 不插入向量i的话,之前的向量位i可以任选,(2^j)种情况

    考虑天际线的限制

    • 不插入向量i,有(2^{j-1})种情况可以继续顶着天际线
    • 如果a[i]==1,还有(2^{j-1})种情况可以小于天际线
    • a[i]==1时可以插入向量i

    然后我的转移方程写的好丑啊....然后鏼鏼鏼了一个简短的写法

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    #define pii pair<int, int>
    #define fir first
    #define sec second
    const int N=40, P=1e9+7;
    inline ll read() {
        char c=getchar(); ll x=0, f=1;
        while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
        while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    
    int n, f[N][N][2], a[N], len;
    ll mi[N];
    inline void mod(int &x) {if(x>=P) x-=P;}
    int dfs(int d, int j, int sky) { //printf("dfs %d %d %d
    ",d,j,sky);
    	if(d==0) return 1;
    	if(f[d][j][sky] != -1) return f[d][j][sky];
    	int &now = f[d][j][sky], lim = sky ? a[d] : 1;
    	now=0;
    	if(!sky) {
    		mod(now += mi[j] * dfs(d-1, j, 0) %P );
    		mod(now += dfs(d-1, j+1, 0)%P );
    	} else {
    		mod(now += (j==0 ? 1 : mi[j-1]) * dfs(d-1, j, sky && 0==lim) %P);
    		if(a[d]==1) mod(now += dfs(d-1, j+1, sky && 1==lim)%P ), 
    			mod(now += (j==0 ? 0 : mi[j-1]) * dfs(d-1, j, sky && 1==lim) %P );
    	}
    	//for(int i=0; i<=lim; i++) {
    	//	mod(now += (j==0 ? !i : mi[j-1]) * dfs(d-1, j, sky && i==lim) %P);
    	//	if(i==1) mod(now += dfs(d-1, j+1, sky && i==lim));
    	//}
    
    	return now;
    }
    int main() {
    	freopen("in","r",stdin);
    	mi[0]=1;
    	for(int i=1; i<=30; i++) mi[i] = (mi[i-1]<<1)%P;
    	n=read();
    	while(n) a[++len]=n&1, n>>=1;
    	memset(f, -1, sizeof(f));
    	printf("%d", dfs(len, 0, 1));
    }
    
  • 相关阅读:
    Java spring自查笔记
    C#设置IP地址 用WMI
    idea换成护眼色
    WPF布局的6种面板
    spring注解
    c# 播放mp3
    Python 提示 “No matching distribution found for MySQLdb”
    Python3链接数据库报错:Connection.__init__() takes 1 positional argument but 5 positional arguments (and 1 keywordonly argument) were given
    安装Mysql数据库及配置相关环境变量
    Python中文件命名的注意事项
  • 原文地址:https://www.cnblogs.com/candy99/p/6657626.html
Copyright © 2011-2022 走看看