1 条题解
-
-1
luogu
#include<bits/stdc++.h> using namespace std; long long val_fac[20],val_pow[10]; long long step_1[20]; void decontor(int n,int p)//逆康托展开 { vector<int>mus,ans; int now=p-1,i; for(i=1;i<=n;i++) mus.push_back(i); for(i=n;i>=1;i--) { int l=now/val_fac[i-1]; now=now%val_fac[i-1]; ans.push_back(mus[l]); mus.erase(mus.begin()+l); } for(i=0;i<n;i++) step_1[i+1]=ans[i]; } int Digit(int num)//找位数 { int sum=0; while(num) { num/=10; sum++; } return sum; } void change(long long &n)//改成下一个幸运数 { long long ans=n; int sum=0; while(ans%10==7)//即上文说的找法 { ans/=10; n-=3*(int)pow(10,sum); sum++; } n+=3*(int)pow(10,sum); } bool check(int val)//检查是否满足幸运数的条件 { while(val) { if(val%10!=4&&val%10!=7) return 0; val/=10; } return 1; } int main() { int p,i,n; long long ans=0; scanf("%d %d",&n,&p); val_fac[0]=1; val_pow[0]=1; for(i=1;i<=15;i++)//逆康托展开前置 val_fac[i]=val_fac[i-1]*i; int dig=Digit(n);//求位数 for(i=1;i<=dig;i++)//预处理 val_pow[i]=val_pow[i-1]*2; if(p>val_fac[min(n,13)])//判断-1 { printf("-1"); return 0; } decontor(min(n,13)/*最多13位,否则就不行了*/,p); if(n>13) { if(n>19)//不会影响到任何低于dig位的幸运数 for(i=1;i<dig;i++) ans+=val_pow[i]; if(n>16&&n<20)//会影响到7 ans++; for(i=1;i<=13;i++)//在逆康托展开中使用的是1~13,需要加回来 step_1[i]=step_1[i]+n-13; long long now=0,biggest=0; for(i=1;i<=dig;i++)//找到dig位的幸运数的最小值和最大值 now*=10,now+=4,biggest*=10,biggest+=7; if(n-13>=biggest)//不会影响到dig位的所有幸运数 ans+=val_pow[dig],now=n-12/*防止进入循环*/; while(now<=n-13&&now!=biggest) { ans++; change(now); } if(now<=n-13&&now==biggest) ans++; for(i=1;i<=13;i++)//暴力查找 { if(check(n+i-13)&&check(step_1[i])) ans++; } } else { if(step_1[4]==4||step_1[4]==7) ans++; if(step_1[7]==4||step_1[7]==7) ans++; } printf("%lld",ans); return 0; }
- 1
信息
- ID
- 384
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 2
- 已通过
- 2
- 上传者