一:C - Round Numbers
求在[a,b]区间内有多少个数满足该数的二进制0的个数大于等于1的个数
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef int ll;
ll dp[100][100],bin[100];
//其实是排列组合问题
//dp[i][j]表示从i个里面挑j个的情况数
void init(){
for(ll i=0;i<=100;i++){
for(ll j=0;j<=i;j++){
if(!j||j==i){
dp[i][j]=1;
}
else dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
}
}
}
//将其二进制分解开
void getchange(ll n){
bin[0]=0;
while(n){
bin[++bin[0]]=n&1;
n>>=1;
}
}
ll sum(ll n){
getchange(n);
ll ans=0;
//先计算位数比n小的,所以bin[0]-1;
//有最高位肯定为1,所以bin[0]-2
for(ll i=1;i<=bin[0]-2;i++){
for(ll j=i/2+1;j<=i;j++){
ans+=dp[i][j];
}
}
//zero表示已经数了多少零
ll zero=0;
for(ll i=bin[0]-1;i>=1;i--){
//如果遍历到的是1,将其变为0,看看后面的i-1个数里还需至少多少零才能满足条件
//至少是(b[0]+1)/2-(zero+1)个
//解方程(zero+1)+x=(b[0]+1)/2,解出x,之所以是(b[0]+1)/2,是因为向上取整
if(bin[i])
for(ll j=(bin[0]+1)/2-(zero+1);j<=i-1;j++)
{
ans+=dp[i-1][j];
}
else zero++;
}
return ans;
}
int main(){
ll a,b;
init();
while(cin>>a>>b){
cout<<sum(b+1)-sum(a)<<endl;
}
return 0;
}
二:求[a,b]内的漂亮数个数
定义:一个数是其每一位的倍数称为漂亮数
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll dp[40][50][2530],bit[40],has[2530];
//一个数是其每一位的倍数,则就是其所有位的最小公倍数的倍数
//1~9的最小公倍数是2520,但是这只是最大的最小公倍数
//所有数进行组合的最小公倍数是不连续的,实际上他们任意组合的最小公倍数仅有48个
//所以dp[n][lcm][mod]范围如上
//这48个最小公倍数用哈希数组来存
ll gcd(ll a,ll b){
while(b){
ll t=a%b;
a=b;
b=t;
}
return a;
}
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}
void init(){
memset(has,0,sizeof(has));
ll cnt=1;
for(ll i=1;i<=2520;i++){
if(2520%i==0){//能整除2520的一定属于上述的哈希数组
has[i]=cnt++;
}
}
}
//POS代表搜索但的位,pre代表到POS位的数的最小公倍数
//mod代表到POS位对2520取模的值
//limit代表限制条件
ll dfs(ll pos,ll pre,ll mod,ll limit){
//搜索到底,返回该数是否合法
if(pos<=0){
//mod是该数除以2520后的余数
//如果该余数是该数所有位的最小公倍数的倍数
//就是满足条件的漂亮数
return mod%pre==0;
}
//记忆化搜索
//如果该状态下不受限制并且dp已经被求出,说明不用该状态不许重复求一次
if(!limit&&dp[pos][has[pre]][mod]!=-1){
return dp[pos][has[pre]][mod];//直接return
}
//如果受限制,说明上一位取到了最大值,所以现在位最大是该数在该数位的最大值
//如果不受限制,可取0~9的任意
ll up=limit?bit[pos]:9;
ll ans=0;
for(ll i=0;i<=up;i++){
//对于mod的更新,可以想一下除法的运算的模拟过程
if(i==0){
ans+=dfs(pos-1,pre,mod*10%2520,limit&&i==bit[pos]);
}
else {
//如果i不是0,更新最小公倍数
ans+=dfs(pos-1,lcm(pre,i),(mod*10+i)%2520,limit&&i==bit[pos]);
}
}
//如果没有限制,更新dp
if(!limit){
dp[pos][has[pre]][mod]=ans;
}
return ans;
}
ll solve(ll n){
ll len=0;
while(n){
bit[++len]=n%10;
n/=10;
}
return dfs(len,1,0,1);
}
int main(){
ll t,a,b;
init();
cin>>t;
//初始化dp要在while外面初始化,因为dp表示的是数位0~pos的状态
//与改变的区间无关
memset(dp,-1,sizeof(dp));
while(t--){
cin>>a>>b;
cout<<solve(b)-solve(a-1)<<endl;
}
return 0;
}
// /\ | / |**、
// / \ | / | \
// / \ |/ | / _____ ____ | /
// /------\ |\ |__/ / \ \ /\ / / \ | /
// / \ | \ | / \ \ / \ / /______\ |/
// / \ | \ | \ / \ / \ / \ |
// / \ | \ | \_____/ \/ \/ \_____ |
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
三:不要49
dfs版:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[50][50],b[50];
ll dfs(ll pos,ll limit,ll pre){
//如果能有pos<=0,肯定是合法的
//除了全为0外,但是0也是合法的,
//所以最后输出是要加一,因为多减了一个
if(pos<=0){
return 1;
}
if(!limit&&dp[pos][pre]!=-1){
return dp[pos][pre];
}
ll up=limit?b[pos]:9;
//ans统计没有49的情况
ll ans=0;
for(ll i=0;i<=up;i++){
//如果出现49,直接筛掉
if(pre==4&&i==9){
continue;
}
else {
ans+=dfs(pos-1,limit&&i==b[pos],i);
}
}
if(!limit){
dp[pos][pre]=ans;
}
return ans;
}
ll solve(ll n){
ll len=0;
while(n){
b[++len]=n%10;
n/=10;
}
return dfs(len,1,0);
}
int main(){
ll n,t;
cin>>t;
memset(dp,-1,sizeof(dp));
while(t--){
cin>>n;
cout<<n-solve(n)+1<<endl;
}
}
其他版本:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll dp[22][3],bit[22];
//dp[i][0]....不含有49的状态
//dp[i][1]....不含有49的状态但是最高位是9
//dp[i][2]....含有49的状态
void init(){
//初始化
dp[0][0]=1;dp[0][1]=0;dp[0][2]=0;
for(ll i=1;i<=22;i++){
dp[i][0]=dp[i-1][0]*10-dp[i-1][1];//减掉最高位是9的那一种状态
dp[i][1]=dp[i-1][0];//就是在不含49的状态在最高位加上一个9
dp[i][2]=dp[i-1][2]*10+dp[i-1][1];//随便加上一个数或者最高位是9,加上一个4
}
}
ll cal(ll n){
ll len=0;
while(n){
bit[++len]=n%10;
n/=10;
}
bit[len+1]=0;
ll ans=0;
ll sign=0;
//接下来很难理解
for(ll i=len;i>=1;i--){
ans+=dp[i-1][2]*bit[i];
if(!sign){
if(bit[i]>4)
ans+=dp[i-1][1];
}
else {
ans+=dp[i-1][0]*bit[i];
}
if(bit[i+1]==4&&bit[i]==9){
sign=1;
}
}
if(sign){
ans++;
}
return ans;
}
int main(){
init();
ll t;
cin>>t;
while(t--){
ll n;
cin>>n;
cout<<cal(n)<<endl;
}
return 0;
}
四:不要62和4
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll n,m,dp[40][10],bin[40];
ll dfs(ll pos,ll pre,ll limit){
if(pos<=0)
return 1;
if(!limit&&dp[pos][pre]!=-1){
return dp[pos][pre];
}
ll up=limit?bin[pos]:9;
ll ans=0;
for(ll i=0;i<=up;i++){
if(i==4||pre==6&&i==2)continue;
ans+=dfs(pos-1,i,limit&&i==bin[pos]);
}
if(!limit){
dp[pos][pre]=ans;
}
return ans;
}
ll solve(ll y){
ll len=0;
while(y){
bin[++len]=y%10;
y/=10;
}
return dfs(len,0,1);
}
int main(){
memset(dp,-1,sizeof(dp));
while(cin>>n>>m&&(n!=0||m!=0)){
cout<<solve(m)-solve(n-1)<<endl;
}
return 0;
}
五:不要13并且是13的倍数
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll n,dp[40][4][20],bin[40];
//pre=0;说明还没有出现13,并且上一位也不是1
//pre=1;说明上一位是1(次判)
//pre=2;说明已经出现了13(先判)
ll dfs(ll pos,ll mod,ll pre,ll limit){
if(pos<=0)
return (pre==2&&mod==0);//返回是否有13,并且是否能被13整除
if(!limit&&dp[pos][pre][mod]!=-1){
return dp[pos][pre][mod];
}
ll up=limit?bin[pos]:9;
ll ans=0;
for(ll i=0;i<=up;i++){
ll temp=(mod*10+i)%13;
if(pre==2||(pre==1&&i==3)){
ans+=dfs(pos-1,temp,2,limit&&i==bin[pos]);
}
else if(i==1){
ans+=dfs(pos-1,temp,1,limit&&i==bin[pos]);
}
else {
ans+=dfs(pos-1,temp,0,limit&&i==bin[pos]);
}
}
if(!limit){
dp[pos][pre][mod]=ans;
}
return ans;
}
ll solve(ll y){
ll len=0;
while(y){
bin[++len]=y%10;
y/=10;
}
return dfs(len,0,0,1);
}
int main(){
while(cin>>n){
memset(dp,-1,sizeof(dp));
cout<<solve(n)<<endl;
}
return 0;
}
六:求[a,b]内的十进制数的非零位小于等于3的数的个数
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll dp[30][20],bit[30];
//cnt计数作为第二维进行dp
ll dfs(ll pos,ll limit,ll cnt){
if(pos<=0){
return 1;
}
if(!limit&&dp[pos][cnt]!=-1){
return dp[pos][cnt];
}
ll up=limit?bit[pos]:9;
ll ans=0;
for(ll i=0;i<=up;i++){
if(i==0){
ans+=dfs(pos-1,limit&&i==bit[pos],cnt);
}
else {
if(cnt==3){
break;
}
ans+=dfs(pos-1,limit&&i==bit[pos],cnt+1);
}
}
if(!limit){
dp[pos][cnt]=ans;
}
return ans;
}
ll solve(ll n){
ll len=0;
while(n){
bit[++len]=n%10;
n/=10;
}
return dfs(len,1,0);
}
int main(){
memset(dp,-1,sizeof(dp));
ll t,l,r;
cin>>t;
while(t--){
cin>>l>>r;
cout<<solve(r)-solve(l-1)<<endl;
}
return 0;
}
// /\ | / |**、
// / \ | / | \
// / \ |/ | / _____ ____ | /
// /------\ |\ |__/ / \ \ /\ / / \ | /
// / \ | \ | / \ \ / \ / /______\ |/
// / \ | \ | \ / \ / \ / \ |
// / \ | \ | \_____/ \/ \/ \_____ |
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//