P4317 花神的数论题(数位dp)

这题只需要记录到当前位,之前总共有多少个1即可

因为首先这满足记忆化的条件,也就是可以在计算过的情况下直接范围答案

其次,我们现在需要理解的是,当我们计算出了这个之后,答案是可以直接累乘的

因为在某个数之后计算的所有数,最大值不超过他,也就是他这位所管辖的所有答案。

所以我们可以想到,这样其实就是把所有情况都乘起来了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int mod=1e7+7;
ll n;
vector<int> num;
ll f[200][210][2];
ll dfs(int u,int sum,int sign){
    if(u==(int)num.size()){
        return max(sum,1);
    }
    auto &x=f[u][sum][sign];
    if(x!=-1)
        return x;
    int v=1;
    if(sign)
        v=num[u];
    ll ans=1;
    for(int i=0;i<=v;i++){
        ans=ans*dfs(u+1,i==1?sum+1:sum,sign&&(i==v))%mod;
    }
    return x=ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    while(n){
        num.push_back(n&1);
        n>>=1;
    }
    reverse(num.begin(),num.end());
    memset(f,-1,sizeof f);
    cout<<dfs(0,0,1)<<endl;
    return 0;
}
View Code

 

posted @ 2020-08-20 23:16  朝暮不思  阅读(93)  评论(0编辑  收藏  举报