gym102835K Number with Bachelors
程序员文章站
2024-03-15 15:28:24
...
https://codeforces.com/gym/102835/problem/K
经典比赛结束3s过题
艹我忘记2^64十进制下是19位,一直还以为是long long 的18位卧槽,2^63才是18位,队友发现这个我改了预处理的上界就过了,我吐了
先讨论10进制情况
统计x为上界时,首先位数少于x的肯定每一位随便选,那么这个就可以预处理出来,10个数字选i位放=A(10,i)
然后我们就只要处理前i为与x的前i-1位相等,当前位选j,后面随便选的情况了,那么就枚举第i位为j,且j与前面已经出现的数字不重复,那么后面随便选就是A(10-i,len-i)
当枚举x到某一位出现重复的时候直接break
16进制的时候类似
注意一些细节,比如 0 的时候,也是一位
用__int128代替ull 防止有些地方出问题
#include<bits/stdc++.h>
using namespace std;
typedef __int128 ull;
int n,opt;
int a[110],alen,b[110],blen;
char w[2],s[110];
ull c[21][21],fac[21];
ull sumd[21],sumh[21];
bool vis[20];
inline void init()
{
for(int i=0;i<=20;i++)
c[i][0]=1;
for(int i=1;i<=20;i++)
for(int j=1;j<=20;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
sumd[0]=1;sumd[1]=10;
for(int i=2;i<=20;i++)
{
sumd[i]=9;
for(int j=2;j<=i;j++)
sumd[i]*=10-j+1;
sumd[i]+=sumd[i-1];
}
sumh[0]=1;sumh[1]=16;
for(int i=2;i<=20;i++)
{
sumh[i]=15;
for(int j=2;j<=i;j++)
sumh[i]*=16-j+1;
sumh[i]+=sumh[i-1];
}
fac[0]=1;
for(int i=1;i<=20;i++)
fac[i]=fac[i-1]*i;
}
inline void prework()
{
scanf("%s",w);
scanf("%d",&opt);
}
inline void rd()
{
scanf("%s",s+1);
alen=strlen(s+1);
for(int i=1;i<=alen;i++)
if(s[i]>='0' && s[i]<='9')
a[i]=s[i]-'0';
else
a[i]=s[i]-'a'+10;
}
inline void chg(ull now)
{
if(now==0)
{
alen=1;
a[1]=0;
return;
}
blen=0;ull mod=(w[0]=='d')?10:16;
while(now>0)
b[++blen]=now%mod,now/=mod;
alen=blen;
for(int i=1;i<=alen;i++)
a[i]=b[blen-i+1];
}
inline void print(ull now)
{
if(now==0)
{
puts("0");
return;
}
blen=0;ull mod=(w[0]=='d')?10:16;
while(now>0)
b[++blen]=now%mod,now/=mod;
for(int i=blen;i>=1;i--)
if(b[i]>=0 && b[i]<=9)
putchar(b[i]+'0');
else
putchar(b[i]+'a'-10);
puts("");
}
inline ull calc()
{
if(alen==1)
return a[1]+1;
ull ret=(w[0]=='d')?sumd[alen-1]:sumh[alen-1];
int sum=(w[0]=='d')?10:16;
for(int i=0;i<sum;i++)
vis[i]=false;
bool flag=true;
for(int i=1;i<=alen;i++)
{
for(int j=(i==1)?1:0;j<a[i];j++)
if(!vis[j] && sum-i>=0)
ret+=c[sum-i][alen-i]*fac[alen-i];
if(!vis[a[i]])
vis[a[i]]=true;
else
{
flag=false;
break;
}
}
if(flag) ret++;
return ret;
}
inline void mainwork()
{
if(opt==0)
{
rd();
ull l,r;bool flag=true;
for(int i=0;i<16;i++)
vis[i]=false;
for(int i=1;i<=alen;i++)
if(vis[a[i]])
flag=false;
else
vis[a[i]]=true;
l=calc();
rd();
r=calc();
ull ans=r-l;
if(flag) ans++;
print(ans);
}
else
{
rd();
ull k=0;
for(int i=1;i<=alen;i++)
k=k*(w[0]=='d'?10:16)+a[i];
ull now=0,one=1,x;
if(k>1)
{
for(ull i=63;i>=0;i--)
{
now|=one<<i;
chg(now);
x=calc();
if(x>=k)
now^=one<<i;
if(i==0)
break;
}
}
else
now=-1;
chg(now+1);
x=calc();
if(x==k)
print(now+1);
else
puts("-");
}
}
int main()
{
init();
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
}
return 0;
}
上一篇: 在Java中找出1到n个数字之间的重复数
下一篇: 送分题素数
推荐阅读
-
gym102835K Number with Bachelors
-
row_number(),rank(),dese_rank()区别 博客分类: hadoophive
-
find the happy number 博客分类: 算法 javahappy numberalgorithm
-
#研究JAVAAPI系列--Number类+BigDecimal类#
-
PHP数字前补0的自带函数sprintf 和number_format的用法(详解)
-
191. Number of 1 Bits
-
191. Number of 1 Bits (E)
-
191. Number of 1 Bits
-
【leetcode】191. Number of 1 Bits
-
How to configure pam_tally2 to lock user account after certain number of failed login attempts