zoukankan      html  css  js  c++  java
  • 51Nod 1383 整数分解为2的幂

    51Nod 1383 整数分解为2的幂

    题意

    任何正整数都能分解成2的幂,给定整数N,求N的此类划分方法的数量!由于方案数量较大,输出Mod 1000000007的结果。
    比如N = 7时,共有6种划分方法。

    7=1+1+1+1+1+1+1
     =1+1+1+1+1+2
     =1+1+1+2+2
     =1+2+2+2
     =1+1+1+4
     =1+2+4
    

    输入:输入一个数N(1 <= N <= 10^6)

    输出:输出划分方法的数量Mod 1000000007

    解题思路

    这个题目我开始想到的想法类似于整数划分问题

    整数划分问题中,定义假设函数f(n,m):n为要整数划分的数,m为划分中出现的最大加数

    这里我进行了一些改变:n还是要进行划分的数,m表示为2的指数,如m=2表示的数是$$2^2$$。

    这样$$f(n, m) = fun(n-2^m, m)+fun(n, m-1)$$

    上面的公式表示两部分,一部分是使用了$$2^m$$,一部分是没有使用。

    然后使用记忆化搜索即可,使用二维的数组来进行记录,注意第二维,我们根据输入的范围是1e6,小于2的22次方,所以第二维大小是22解可以了。

    第二种方法

    做完这个题后,我搜了这个题,发现可以用递推的方式来进行

    if(N%2==0) F[N]=F[N-1]+F[N>>1]

    else F[N]=F[N-1]

    • 对于一个偶数,可以让比他小一数的方案全部加一个1得到,也可以让比他小一半的数的方案元素都乘以2得到。

    • 对于奇数只能由比他小的数加一得到。

    代码实现

    //第一种方式
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<sstream>
    typedef long long ll;
    using namespace std;
    const ll llinf = 0x3f3f3f3f3f3f3f3f;
    const int inf=0x3f3f3f3f;
    const double eps=1e-6;
    const int MAXN=1e6+7;
    const ll mod = 1000000007;
    ll n, ans;
    int dp[MAXN][22];
    int dfs(int x, int p){
        if(p<0)
            return 0;
        if(x==0)
            return 1;
        int y = 1<<p;
        if(x<y){
            do{
                y>>=1;
                p--;
            }while(x<y);
        }
        if(dp[x][p]>=0){
            return dp[x][p];
        }
        dp[x-y][p] = dfs(x-y, p) % mod;
        dp[x][p-1] = dfs(x, p-1) % mod;
        return dp[x][p] = (dp[x-y][p] + dp[x][p-1])%mod ;
    }
    int main(){
        cin>>n;
        int max2 = 0;
        memset(dp, -1, sizeof(dp));
        for(int i=0, tmp = 1; tmp<=n; i++){
            max2=i;
            tmp <<= 1;
        }
        // cout<<max2<<endl;
        cout<<dfs(n, max2)<<endl;
        return 0;
    }
    
    //第二种方式
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6;
    const int MOD = 1e9 + 7;
    int f[N + 1];
    
    int main(){
        f[0] = 1;
        f[1] = 1;
        for(int i = 2; i <= N; i++)
            if(i % 2)
                f[i] = f[i - 1];
            else
                f[i] = (f[i - 1] + f[i >> 1]) % MOD;
        int n;
        while(~scanf("%d", &n))
            printf("%d
    ", f[n]);
        return 0;
    }
    
  • 相关阅读:
    【MySQL】(三)文件
    【MySQL】(二)InnoDB存储引擎
    Linux Shell脚本编程-信号捕获
    Linux Shell脚本编程-数组和字符串处理
    Linux Shell脚本编程-函数
    Linux Shell脚本编程-语句控制
    Linux Shell脚本编程-基础2
    Linux Shell脚本编程-基础1
    Awk
    Sed
  • 原文地址:https://www.cnblogs.com/alking1001/p/13719215.html
Copyright © 2011-2022 走看看