[杂题] Codeforces #121C. Lucky Permutation

本文提供了一道CFCF 121C题目的详细解答过程,针对大数问题采用数位DPDP算法求解,并通过暴力计算处理特殊情况。代码实现了高效的求解方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题很 cf 。虽然 n 很大,但由于 K 只有 1e9,所以数列前面大部分数字是在原位的。13!=6227020800,只有后面不到 14 位会变化,后面暴力就好了。
前面的 1n13,数位 DP 求答案。

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100005;
typedef long long LL;
LL n,K,ans,a[25],m,fac[25],f[25][2][2];
int b[20];
bool vis[25];
LL Calc(LL n){
    LL res=0;
    b[0]=0; do b[++b[0]]=n%10, n/=10; while(n);
    f[b[0]+1][0][0]=1;
    for(int i=b[0]+1;i>=2;i--)
     for(int j1=0;j1<=1;j1++)
      for(int j2=0;j2<=1;j2++) if(f[i][j1][j2])
      for(int k=(j2?1:0);k<=(j1?9:b[i-1]);k++) if(k==0||k==4||k==7)
       f[i-1][j1|(k<b[i-1])][j2|(k>0)]+=f[i][j1][j2];
    return f[1][0][1]+f[1][1][1];
}
bool check(int n){
    do{
        if(n%10!=4&&n%10!=7) return false;
        n/=10;
    }while(n);
    return true;
}
int main(){
    freopen("cf121C.in","r",stdin);
    freopen("cf121C.out","w",stdout);
    fac[0]=1; for(int i=1;i<=20;i++) fac[i]=fac[i-1]*i;
    scanf("%d%d",&n,&K); m=max(0LL,n-15);
    if(n<=15&&fac[n]<K) return printf("-1"),0; 
    ans=Calc(m);
    for(int i=m+1;i<=n;i++){
        int now=1; while(K>fac[n-i]) K-=fac[n-i], now++;
        for(int j=1;j<=n-m;j++) if(!vis[j]) if(!(--now)){ a[i-m]=j; vis[j]=true; break; }
        if(check(i)&&check(m+a[i-m])) ans++;
    }
    printf("%I64d\n",ans);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值