題意:求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...