CS 300
题意:定义一个数x的价值为:x十进制表示a[1]a[2]..a[i]中有多少位为偶数.
给出x,分别求出<x,>x中第一个价值比x小的数y.如果不存在则输出-1. x<=1e9.
假如x价值为val
数位DP:先算[1,n]中有多少个价值不超过val-1的数. dp[pos][val]..
题意:定义一个数x的价值为:x十进制表示a[1]a[2]..a[i]中有多少位为偶数.
给出x,分别求出<x,>x中第一个价值比x小的数y.如果不存在则输出-1. x<=1e9.
假如x价值为val
数位DP:先算[1,n]中有多少个价值不超过val-1的数. dp[pos][val]..
二分出一个y 满足[1,y]价值不超过val-1的数和[1,x]价值不超过val-1的数相差正好为1即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+5,mod=1e9+7;
const ll inf=2e15;
ll x,val;
int calc(int x)
{
int res=0;
while(x)
{
res+=((x%10)%2)==0;
x/=10;
}
return res;
}
ll dp[N][15];
int a[N];
ll dfs(int pos,int val,bool flag,bool limit)
{
if(pos==0)
return flag==false;
if(!limit&&!flag&&dp[pos][val]!=-1)
return dp[pos][val];
int up=limit?a[pos]:9;
ll res=0;
for(int i=0;i<=up;i++)
{
if(i%2)
res+=dfs(pos-1,val,flag&&i==0,limit&&i==up);
else
{
int rea=(flag&&i==0)?0:1;
if(rea)
{
if(val>0)
res+=dfs(pos-1,val-1,flag&&i==0,limit&&i==up);
}
else
res+=dfs(pos-1,val,flag&&i==0,limit&&i==up);
}
}
if(!limit&&!flag)
dp[pos][val]=res;
return res;
}
ll solve(ll x,int val)
{
int pos=0;
while(x)
{
a[++pos]=x%10;
x/=10;
}
return dfs(pos,val,true,true);
}
int main()
{
cin>>x;
int val=calc(x)-1;
if(val<0)
{
puts("-1");
return 0;
}
memset(dp,-1,sizeof(dp));
ll num=solve(x,val);
ll l=x,r=inf,le,rg;
while(l<=r)
{
ll mid=l+r>>1;
if(solve(mid,val)-num>=1)
r=mid-1;
else
l=mid+1;
}
rg=r+1;
l=1,r=x-1;
while(l<=r)
{
ll mid=l+r>>1;
if(num-solve(mid,val)>=1)
l=mid+1;
else
r=mid-1;
}
le=l-1+1;
//cout<<rg<<' '<<le<<endl;
cout<<(rg-x)*(x-le)<<endl;
return 0;
}
法2: 要找的数为y1,y2. y1<=x<=y2
求y2 只要在x中找到最右边的偶数位 将其+1 并且把后面变为全1即可. 743253 7432?? 价值不会变小.
求y1 枚举和x的公共前缀以及下一位数.后面全部设为9 找到这些数中满足条件最大的哪一个即可.