51nod 1635 第K個幸運排列

2021-08-09 18:32:20 字數 1419 閱讀 9955

題意:求1-n的全排列中的第k種排列,其中有多少幸運數字處在幸運位置上。幸運數字以及位置的定義為只包含4和7

思路:我們知道13!大於1e9,根據全排列的順序顯然最多只有13個位置在發生重排,那麼我們可以根據輸入的k將n個位置分成兩個部分:前半部分為固定不動的部分(即1,2,3,4,……),後半部分為實際發生了重排的部分,我們對這兩個部分分別計算滿足要求的個數。

我們首先找到第乙個數x,它的階乘大於k,這個數就是發生重排的數的個數,通過這個數我們將n個位置分為左右兩部分。前半部分即從1到n-x的數列,問題就變成了1到n-x有多少個數只包含4和7,這裡可以數字dp或者直接搞,直接搞的話首先算出n-x有多少位(假設有len位),對於1位數到len-1位數,隨意放4或7即可,也就是2的1次方加到2的len-1次方,對於恰好len位的數,我們從高位開始拆解,如果當前位大於7,那麼這一位4和7都能放,後面隨便放;如果當前位等於7,那麼這一位4一定能放,7能不能放繼續看下一位數;如果當前位是5和6,那麼這一位放4,後面隨便放;如果當前位為4,接著看後面;當前位小於4那麼這一位沒法放數了,結束計數。

後半部分因為數的個數非常少,我們將k進行逆康托展開,還原出後半部分原來的排列,對位置和數都check一下是否只包含4和7,統計一下滿足的個數。

最後兩部分計數加起來就是答案了。k大於n!的輸出-1。

**:

#includeusing namespace std;

typedef long long ll;

ll fac[20],p[40];

int a[20];

ll solve(ll x) else if (a[i]==7) else if (a[i]>4) else if (a[i]==4) else if (a[i]<4)

}for (int i=1;i<=pos-1;i++) res+=p[i];

return res;

}bool vis[20];

int s[20];

void reverse_cantor(int n,ll k,int base)

return true;

}int main()

for (int i=1;i<=32;i++) p[i]=p[i-1]*2;

ll n,k;

scanf("%lld%lld",&n,&k);

if (n<13 && fac[n]=10) tmp/=10,len++;

ll ans=solve(pos);

reverse_cantor(n-pos,k,pos);

for (int i=start;i<=n;i++)

printf("%lld\n",ans);

return 0;

}

第K個幸運數

4和7是兩個幸運數字,我們定義,十進位制表示中,每一位只有4和7兩個數的正整數都是幸運數字。前幾個幸運數字為 4,7,44,47,74,77,444,447 現在輸入乙個數字k,輸出第k個幸運數。第一行乙個數字t t 1000 表示測試資料的組數。對於每組測試資料,輸出乙個數k 1 k 10 18 ...

第K個幸運數字(4 7)

題目 4和7是兩個幸運數字,我們定義,十進位制表示中,每一位只有4和7兩個數的正整數都是幸運數字,前幾個幸運數字為 4,7,44,47,74,77,444,447 輸出第k個數字。思路是 將4換成0,7換成1,那麼 4,7,44,47,74,77,444,447.變成了 0,1,00,01,10,1...

51Nod 1686 第K大區間

題意 中文題,定義乙個區間的值為其眾數出現的次數。現給出n個數,求將所有區間的值排序後,第k大的值為多少。離散化二分答案加尺取判斷 include include includeusing namespace std const int maxn 100006 typedef long long l...