zoukankan      html  css  js  c++  java
  • CF388D-Fox and Perfect Sets【dp,线性基】

    正题

    题目链接:https://www.luogu.com.cn/problem/CF388D


    题目大意

    给出(k),求有多少个集合(S)满足(Ssube [1,k])

    [ain S,bin SRightarrow a xor bin S ]

    (1leq kleq 10^9)


    解题思路

    发现这个性质和线性基的很像,问题可以转换为问有多少个本质不同的线性基最大异或和不超过(k)

    在我们求(k)大异或和的时候我们把所有相同的线性基转换成了一个相同的形式满足对于它的数组(d)

    • (d_i)如果不是零那么其第(i)位是(1)且对于所有(j eq i)都有(d_j)的第(i)位为(0)

    此时统计这种线性基的数量就不会算重了,并且全部的(d)异或起来一定是最大的。

    然后然后就(dp)了,设(f_{i,j,0/1})表示到二进制第(i)位,前面有(j)(d)不是(0),现在的异或和的前(i)位到达/每到达(k)的上限。

    转移的时候对于一位(d),如果填(0)那么就需要考虑前面的(d)有多少个加上这一位。为了方便转移可以预处理一下(g_i)表示(i)个东西选出奇数个的方案就好了。

    时间复杂度(O(log^2 k))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll P=1e9+7,N=35;
    ll n,ans,f[N][N][2],C[N][N],g[N];
    signed main()
    {
    	C[0][0]=1;
    	for(ll i=1;i<N;i++)
    		for(ll j=0;j<=i;j++)
    			C[i][j]=(C[i-1][j]+(j?C[i-1][j-1]:0))%P;
    	for(ll i=1;i<N;i++)
    		for(ll j=1;j<=i;j+=2)g[i]+=C[i][j];
    	scanf("%lld",&n);f[30][0][1]=1;
    	for(ll i=29;i>=0;i--)
    		for(ll j=0;j<30-i;j++){
    			if((n>>i)&1){
    				(f[i][j+1][1]+=f[i+1][j][1]%P)%=P;
    				(f[i][j][1]+=f[i+1][j][1]*g[j]%P)%=P;
    				(f[i][j+1][0]+=f[i+1][j][0]%P)%=P;
    				(f[i][j][0]+=f[i+1][j][0]*(1ll<<j)%P+f[i+1][j][1]*((1ll<<j)-g[j])%P)%=P;
    			}
    			else{
    				(f[i][j][1]+=f[i+1][j][1]*((1ll<<j)-g[j])%P)%=P;
    				(f[i][j+1][0]+=f[i+1][j][0]%P)%=P;
    				(f[i][j][0]+=f[i+1][j][0]*(1ll<<j)%P)%=P;
    			}
    		}
    	for(ll j=0;j<30;j++)(ans+=f[0][j][0]+f[0][j][1])%=P;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    (网络编程)基于tcp(粘包问题) udp协议的套接字通信
    (网络编程)理论 原理
    (网络编程) 介绍
    C++开源代码项目汇总
    Facial Landmark Detection
    人脸对齐ASM-AAM-CLM的一些总结
    Ello讲述Haar人脸检测:易懂、很详细、值得围观
    显示形状回归算法(ESR)代码介绍
    百度图像搜索探秘
    人脸特征点检测
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15408312.html
Copyright © 2011-2022 走看看