牛客练习赛13D

定义一个数字为幸运数字当且仅当它的所有数位都是4或者7。
比如说,47、744、4都是幸运数字而5、17、467都不是。
现在想知道在1...n的第k小的排列(permutation,https://en.wikipedia.org/wiki/Permutation)中,有多少个幸运数字所在的位置的序号也是幸运数字。

解法:康拓展开模拟即可,,最多置换了13位(全排列超过了1e9,前面的直接枚举所有幸运数字)

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pli pair<long long,int>
#define pi acos(-1.0)
#define ll long long
#define mod (998244353)
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double g=10.0,eps=1e-12;
const int N=3200+10,maxn=1000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
ll f[N];
void init()
{
    f[0]=f[1]=1;
    for(int i=2;i<=13;i++)
    {
        f[i]=f[i-1]*i;
//        printf("%lld ",f[i]);
    }
//    puts("");
}
int cal(ll x,ll y)
{
    while(x)
    {
        if(x%10!=4&&x%10!=7)return 0;
        x/=10;
    }
    while(y)
    {
        if(y%10!=4&&y%10!=7)return 0;
        y/=10;
    }
    return 1;
}
int main()
{
    init();
//    printf("%d
",cal(4,4));
    ll n,k,ans=0;
    scanf("%lld%lld",&n,&k);
    k--;
    vector<ll>v;
    for(ll i=max(1ll,n-13+1);i<=n;i++)v.pb(i);
    for(ll i=max(1ll,n-13+1);i<=n;i++)
    {
//        printf("%lld
",f[n-i]);
        ll x=k/f[n-i];
        ll r=k%f[n-i];
        k=r;
        sort(v.begin(),v.end());
//        for(int j=0;j<v.size();j++)printf("%d ",v[j]);
//        printf("%d+++%d++++%d--%d
",i,x,v[x],cal(i,v[x]));
        ans+=cal(i,v[x]);
        v.erase(v.begin()+x);
    }
    v.clear();
    for(int i=1;i<=10;i++)
    {
        for(int j=0;j<(1<<i);j++)
        {
            ll res=0;
            for(int k=0;k<i;k++)
            {
                if((j>>k)&1)res=res*10+4;
                else res=res*10+7;
            }
            v.pb(res);
        }
    }
//    for(int i=0;i<v.size();i++)printf("%lld
",v[i]);
    sort(v.begin(),v.end());
    for(int i=0;i<v.size();i++)
        if(v[i]<=max(0ll,n-13))
            ans++;
    printf("%lld
",ans);
    return 0;
}
/********************
 
********************/
View Code

 

原文地址:https://www.cnblogs.com/acjiumeng/p/8595281.html