3209: 花神的数论题
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2267 Solved: 1040
[Submit][Status][Discuss]
Description
背景
众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。
描述
话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。
花神的题目是这样的
设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你
派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。
Input
一个正整数 N。
Output
一个数,答案模 10000007 的值。
Sample Input
样例输入一
3
3
Sample Output
样例输出一
2
2
HINT
对于样例一,1*1*2=2;
数据范围与约定
对于 100% 的数据,N≤10^15
// 数位dp模板题 10^15最多52个1,枚举1的个数来统计就行了。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const ll mod=1e7+7; int bit[60],maxv; ll dp[60][60]; ll pow_mod(ll a,ll b) { if(b==0) return 1; ll x=pow_mod(a,b/2); ll ans=x*x%mod; if(b&1) ans=ans*a%mod; return ans; } ll dfs(int pos,int x,int limt) { if(pos<=0) return x==maxv; if(!limt&&dp[pos][x]!=-1) return dp[pos][x]; ll ans=0; int maxb=(limt?bit[pos]:1); for(int i=0;i<=maxb;i++){ ans+=dfs(pos-1,x+i,limt&&(i==maxb)); } if(!limt) dp[pos][x]=ans; return ans; } void solve(ll n) { int nu=0; while(n){ bit[++nu]=(n&1); n>>=1; } ll ans=1; for(int i=1;i<=nu;i++){ memset(dp,-1,sizeof(dp)); maxv=i; ll tmp=dfs(nu,0,1); ans=ans*pow_mod(i,tmp)%mod; } printf("%lld ",ans); } int main() { ll n; scanf("%lld",&n); solve(n); return 0; }
1799: [Ahoi2009]self 同类分布
Time Limit: 50 Sec Memory Limit: 64 MBSubmit: 1245 Solved: 535
[Submit][Status][Discuss]
Description
给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
Input
Output
Sample Input
10 19
Sample Output
3
HINT
【约束条件】1 ≤ a ≤ b ≤ 10^18
代码:
//数位dp模板题 10^18的数数位和最大是153,然后枚举数位和然后就行了。刚开始还傻到想要求前153个数的lcm。。。。 //dfs时记录余数pre 和数位和sum。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll dp[20][200][200],po[20]; int bit[20]; ll dfs(int pos,int mod,int sum,int pre,bool w){ if(pos<=0) return pre==0&&sum==mod; if(!w&&dp[pos][sum][pre]!=-1) return dp[pos][sum][pre]; ll ans=0; int maxb=(w?bit[pos]:9); for(int i=0;i<=maxb;i++){ ans+=dfs(pos-1,mod,sum+i,(pre+i*po[pos])%mod,w&&(i==maxb)); } if(!w) dp[pos][sum][pre]=ans; return ans; } ll solve(ll x) { int nu=0; while(x){ bit[++nu]=x%10; x/=10; } ll ans=0; for(int mod=1;mod<=nu*9;mod++){ memset(dp,-1,sizeof(dp)); ans+=dfs(nu,mod,0,0,1); } return ans; } int main() { po[1]=1; for(int i=2;i<=18;i++) po[i]=po[i-1]*1LL*10; ll a,b; scanf("%lld%lld",&a,&b); printf("%lld ",solve(b)-solve(a-1)); return 0; }