[bzoj1799]同类分布 [bzoj4521]手机号码
2016-04-21 07:42
225 查看
1799: [Ahoi2009]self 同类分布
Time Limit: 50 Sec Memory Limit: 64 MBSubmit: 824 Solved: 325
[Submit][Status][Discuss]
Description
给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
Sample Input
10 19
Sample Output
3
HINT
1 ≤ a ≤ b ≤ 10^18
这个数最多有18位,每一位最大是9,所以最多就除到162
这样就可以枚举取模的数是什么,dp一下当前的答案。
在模Mod的时候的f[i][j][k][o]表示第i位时,各数位之和是j,当前的数模Mod之后是k,是否卡着上面的位的方案数。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define LL long long int o[20]; LL f[20][170][170][2],n,m,pow[20]; // i位,数位的和是j,这个数模后是k,是否卡着上限 inline LL calc(LL x){ LL ans=0; int len=0,i,j,p,q,Mod,sum=0,k; while(x) o[++len]=x%10LL,x/=10LL; for(i=1;i<=len/2;++i) swap(o[i],o[len-i+1]); for(sum=o[1],i=2;i<=len;++i) sum+=9; for(Mod=1;Mod<=sum;++Mod){ memset(f,0,sizeof(f)); f[0][0][0][1]=1; for(i=0;i<len;++i) for(j=0;j<=Mod;++j) for(k=0;k<Mod;++k) for(p=0;p<=1;++p) if(f[i][j][k][p]) for(q=0;q<=9;++q){ if(p==1&&o[i+1]<q) break; int o0=q+j,o1=(k+(pow[len-(i+1)]%(LL)Mod)*q%Mod)%Mod; int o2=(p==0)?0:(o[i+1]==q); f[i+1][o0][o1][o2]+=f[i][j][k][p]; } ans+=f[len][Mod][0][0]+f[len][Mod][0][1]; } return ans; } int main(){ int i; for(pow[0]=1LL,i=1;i<=18;++i) pow[i]=pow[i-1]*10LL; scanf("%lld%lld",&n,&m); printf("%lld\n",calc(m)-calc(n-1)); }
4521: [Cqoi2016]手机号码
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 161 Solved: 99
[Submit][Status][Discuss]
Description
人们选择手机号码时都希望号码好记、吉利。比如号码中含有几位相邻的相同数字、不含谐音不
吉利的数字等。手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号
码单独出售。为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数
量。
工具需要检测的号码特征有两个:号码中要出现至少3个相邻的相同数字,号码中不能同
时出现8和4。号码必须同时包含两个特征才满足条件。满足条件的号码例如:13000988721、
23333333333、14444101000。而不满足条件的号码例如:1015400080、10010012022。
手机号码一定是11位数,前不含前导的0。工具接收两个数L和R,自动统计出[L,R]区间
内所有满足条件的号码数量。L和R也是11位的手机号码。
Input
输入文件内容只有一行,为空格分隔的2个正整数L,R。
10^10 < = L < = R < 10^11
Output
输出文件内容只有一行,为1个整数,表示满足条件的手机号数量。
Sample Input
12121284000 12121285550
Sample Output
5
样例解释
满足条件的号码: 12121285000、 12121285111、 12121285222、 12121285333、 12121285550
状态的意思写在程序里了
code:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define LL long long LL f[15][15][2][2][2][2][2],n,m; /*第i位时当前这一位的数是什么前两位是否一样是否有三个连续的48的个数是否卡着上一位*/ inline LL calc(LL x){ int i,o0,o1,o2,o3,o4,o5,o6,o,o7,a,b,c,d,ni[20]; memset(ni,0,sizeof(ni)); while(x) ni[++ni[0]]=x%10,x/=10LL; for(i=1;i<=ni[0]/2;++i) swap(ni[i],ni[ni[0]-i+1]); memset(f,0,sizeof(f)); f[0][10][0][0][0][0][1]=1; for(o0=0;o0<ni[0];++o0) for(o1=0;o1<=10;++o1) for(o2=0;o2<=1;++o2) for(o3=0;o3<=1;++o3) for(o4=0;o4<=1;++o4) for(o5=0;o5<=1;++o5) for(o6=0;o6<=1;++o6) if(f[o0][o1][o2][o3][o4][o5][o6]) for(o7=0;o7<=9;++o7){ if(o4+o5==2||(o7>ni[o0+1]&&o6)) continue; a=(o1==o7);b=o3?o3:(a+o2==2); c=o4?o4:(o7==4);d=o5?o5:(o7==8); if(c+d==2) continue; o=o6?(o7==ni[o0+1]):o6; f[o0+1][o7][a][b][c][d][o]+=f[o0][o1][o2][o3][o4][o5][o6]; } LL ans=0; for(o0=0;o0<=9;++o0) for(o1=0;o1<=1;++o1) for(o2=0;o2<=1;++o2) for(o3=0;o3<=1&&o2+o3<2;++o3) ans+=f[ni[0]][o0][o1][1][o2][o3][0]; //cout<<ans<<endl; return ans; } int main(){ scanf("%lld%lld",&n,&m); printf("%lld\n",calc(m+1)-calc(n)); }
相关文章推荐
- HARK学习(八)--LoadSourceLocation
- 梦见教训学生的周公解梦
- salesforce 零基础学习(十七)Trigger用法
- vi/vim常用命令
- 修改后的神经网络
- AFN 获取数据,数据解析:JSON 介绍
- Mini-Shell without pipes
- 团队项目个人工作总结(4月21日)
- 我是一个Java class
- Linux磁盘管理
- 站立会议03
- Windows UWP
- 在浏览器中下载Google play store软件
- 个人工作总结03
- 转载/JSTL/attribute value does not accept any express
- 数位dp的一种姿势
- 第一冲刺阶段——个人工作总结04
- spark种的名词解释
- Android adb shell学习心得(四)
- leetcode 1. two sum