zoukankan      html  css  js  c++  java
  • [bzoj3209]花神的数论题_数位dp

    花神的数论题 bzoj-3209

    题目大意:sum(i)表示i的二进制表示中1的个数,求$prodlimits_{i=1}^n sum(i)$

    注释:$1le nle 10^{15}$。

    想法:喷一下题目...神tm数论题,明明是个dp。

    显然,如果稍微打个表的话就可以发现,有很多数的sum是相等的,我们不想重复乘这么多次,所以我们想到将所有sum相等的数弄到一起然后快速幂。这样,就不难想到数位dp

    状态:dp[i][j]表示i位,sum值是j的个数。

    转移是容易的,按照数位dp的边界特判就行了。

    最后,附上丑陋的代码... ...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long int ll;
    const int MAXN=60+5;
    const ll mod=10000007;
    ll n, Ans;
    ll C[MAXN][MAXN];
    int l,wei[MAXN];
    void pre()
    {
    	for (int i=0;i<=60;++i)
    		C[i][0]=1;
    	for(int i=1;i<=60;i++)
    		for(int j=1;j<=i;++j)
    			C[i][j]=C[i-1][j-1]+C[i-1][j];
    }
    ll Solve(int x)
    {
    	ll sum=0;
    	for(int i=l;i>=1;i--)
    	{
    		if(wei[i]==1)
    		{
    			sum+=C[i-1][x];
    			--x;
    		}
    		if(x<0) break;
    	}
    	return sum;
    }
    ll quick_power(ll x,ll y)
    {
    	ll ans=1;
    	while(y)
    	{
    		if(y&1) ans=(ans*x)%mod;
    		y>>=1;
    		x=(x*x)%mod;
    	}
    	return ans;
    }
    int main()
    {
    	pre();
    	scanf("%lld",&n);
    	++n;
    	l=0;
    	while(n)
    	{
    	  wei[++l]=n&1;
    	  n>>=1;
    	}
    	Ans=1ll;
    	for(int i=1;i<=l;i++)
    	{
    		Ans=Ans*quick_power(i,Solve(i))%mod;
    	}
    	printf("%lld
    ",Ans);
    	return 0;
    }
    

    小结:有意思...别被题面迷惑了(@EdwardFrog) 

  • 相关阅读:
    ShoreWall不错的Linux防火墙 规格严格
    数据挖掘 规格严格
    GLIBC 规格严格
    Solr/Lucene Wiki 规格严格
    Zope??? 规格严格
    用Apache htpasswd管理SVN帐户
    假装
    拼包函数及网络封包的异常处理(含代码)
    云计算
    云计算
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9291381.html
Copyright © 2011-2022 走看看