zoukankan      html  css  js  c++  java
  • BZOJ:3209: 花神的数论题

    今天居然没参考任何资料解决了这道数位DP,事先只是搞一道数论题练练;

    思路:求SUM[1]-SUM[N]的二进制的乘积mod1000000007;

           N<=10^15;BZOJ的题不会是几个简单的FOR就完结的,

       假如N的二进制是:1001001;

                        位数:1234567

     那么当第一位是0的情况:那么数就是000000-111111

                                        序列号:  123456-123456

     发现我们可以用排列组合算出二进制有1-6个1的数比如:1个1就是C[6][1],2个1就是C[6][2],......

    当第一位是0:那么就看下一位为1的位置,去枚举计算,注意第一位为1后面全部为0的情况我们要考虑。

    说的比较不靠谱。

    比如:第一位为0;那么枚举1-6位的位置;

           当第一位为1是:可能1-6位都为0,所以前面的这个1要考虑,

    可以自己画画

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<math.h>
    using namespace std;
    #define N 10000007
    typedef long long ll;
    ll c[61][61];
    int b[61];
    ll kuai(ll a,ll b)//快速米
    {
        ll ans=1;
        while (b)
        {
            if (b&1) ans=ans*a%N;
            a=a*a%N;
            b/=2;
        }
        return ans;
    }
    
    int main()
    {
        ll n;
        int t=0;
        for (int i=0;i<=61;i++)//预先计算排列组合
        c[i][0]=1;
        for (int i=1;i<=60;i++)
        for (int j=1;j<=60;j++)
        c[i][j]=(c[i-1][j]+c[i-1][j-1]);
        
        scanf("%lld",&n);
        while (n)
           {
            t++;
            if (n&1) b[t]=1;
            n/=2;
          }
         int k=0; ll ans=1;
          for (int i=t;i>=1;i--)
          if (b[i])
            {
    
                ans=ans*(k+1)%N;
                for (int j=1;j<=i-1;j++)
                ans=ans*kuai(j+k,c[i-1][j])%N;
                k++;
            }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

                                      

  • 相关阅读:
    Elasticsearch-PHP 索引操作2
    Elasticsearch-PHP 索引操作
    Linux系统编程1_C标准函数库和系统调用
    Git命令_git commit
    Git命令_git log
    Linux27_配置samba
    计算机网络12_整理
    理解操作系统8——字符设备与块设备
    网站开发基础知识3_会话和cookie
    网站开发基础知识2_前后端分离
  • 原文地址:https://www.cnblogs.com/forgot93/p/3809159.html
Copyright © 2011-2022 走看看