zoukankan      html  css  js  c++  java
  • P3226 [HNOI2012]集合选数

    https://www.luogu.org/problem/P3226

    考虑构造矩阵
    1 3 9 27......
    2 6 18 54......
    4 12 36 108......
    ......

    发现在这个矩阵上一个合法的集合是一个满足选择的数字不相邻的集合,由于行数列数的大小都是log级别的,可以直接状压dp。
    此外,不仅要以1位左上角做dp,还要分别以所有既不是2的倍数,也不是3的倍数的数字做dp。
    把所有方案乘起来即可。

    #include<iostream>
    #include<cctype>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<algorithm>
    #define N 22
    #define S 110000
    #define eps 1e-7
    #define inf 1e9+7
    #define ll long long
    using namespace std;
    inline ll read()
    {
    	char ch=0;
    	ll x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*flag;
    }
    const ll mo=1000000001;
    bool flag[S];
    ll n,dp[N][S];
    ll solve(ll k)
    {
    	dp[0][0]=1;
    	ll x,a,b,last=0,ans=0;
    	for(x=k,a=0;x<=n;x*=2)a++;
    	for(ll i=1;i<=a;i++,k*=2)
    	{
    		for(x=k,b=0;x<=n;x*=3)b++;
    		for(ll s=0;s<(1<<b);s++)if(flag[s])
    		{
    			dp[i][s]=0;
    			for(ll p=0;p<(1<<last);p++)if(flag[p])
    			if(!(s&p))dp[i][s]=(dp[i][s]+dp[i-1][p])%mo;
    		}
    		last=b;
    	}
    	for(ll s=0;s<(1<<last);s++)ans=(ans+dp[a][s])%mo;
    	return ans;
    }
    int main()
    {
    	n=read();
    	ll ans=1;
    	for(ll s=0;s<S;s++)
    	{
    		flag[s]=true;
    		for(ll i=0;i<=15;i++)
    		if(((1<<i)&s)&&(1<<(i+1)&s))
    		flag[s]=false;
    	}
    	for(ll i=1;i<=n;i++)
    	if(i%2&&i%3)ans=(ans*solve(i))%mo;
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    第一章 ASP.net C#基本语法(A篇 变量) 王道
    yarn和npm常用命令
    新的开始 Pit
    mysql关键字执行顺序
    log4j2.14.0漏洞攻击复现
    elastic search why so good?
    C# 使用网易126邮箱发件和收件
    分享
    再也没有人......
    数据库附加不上 未能在sysindexes中。。。
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/10159691.html
Copyright © 2011-2022 走看看