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; }
没有人不辛苦,只有人不喊疼