codeforces 121C C. Lucky Permutation(数论+构造)
2015-08-26 20:17
447 查看
题目链接:
codeforces 121C题目大意:
问字典序第k大的1~n的排列中的只由4和7组成的数为位置上具有相同性质的数的个数。题目分析:
首先因为k≤109k \leq 10^9,所以需要变化的位最多只有13位,因为13位就可以导致字典序推进13!所以除了末尾的13个数位置有变化,其他的数的位置都没有变化,所以我们直接枚举符合条件的数的个数即可,因为他们的数值和下标相同,然后对于最后的13位,我们可以利用组合数学快速求出第k个排列的末尾13位,然后直接枚举这13位,然后判断合法不合法即可。
AC代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; typedef long long LL; int ans,n,k,m,x; LL fac[15]; int num[15]; bool mark[15]; void dfs ( int i = 0 , LL num = 0 ) { if ( num && num <= m ) ans++; if ( i == 9 ) return; dfs ( i+1 , num*10+4 ); dfs ( i+1 , num*10+7 ); } void make ( int i = 1 ) { if ( i > x ) return; int j = 1,t; while ( mark[j] ) j++; while ( k >= fac[x-i] ) { j++; while ( mark[j] ) j++; k -= fac[x-i]; } while ( mark[j] ) j++; num[i] = j+m; mark[j] = 1; make( i+1 ); } int main ( ) { fac[0] = 1LL; for ( LL i = 1 ; i < 15 ; i++ ) fac[i] = fac[i-1]*i; while ( ~scanf ( "%d%d" , &n , &k ) ) { ans = 0; memset ( mark , 0 , sizeof ( mark ) ); if ( n < 15 && fac < k ) { puts ( "-1" ); continue; } for ( int i = 0 ; i < 15 ; i++ ) if ( fac[i] >= k ) { x = i; break; } m = n-x; dfs ( ); k--; make( ); for ( int i = m+1 ; i <= n ; i++ ) { bool flag = true; int temp = i; while ( temp ) { if (temp%10 != 4 && temp%10 != 7 ) flag = false; temp /= 10; } temp = num[i-m]; while ( temp ) { if ( temp%10 != 4 && temp%10 != 7 ) flag = false; temp /= 10; } if ( flag ) ans++; } printf ( "%d\n" , ans ); } }
相关文章推荐
- LeetCode题解:Happy Number
- 浅谈 OneAPM 在 express 项目中的实践
- UI空间大全
- HTML 5 <input> placeholder 属性
- HTML 5 <input> placeholder 属性
- HTML 5 <input> placeholder 属性
- 浅谈 OneAPM 在 express 项目中的实践
- angularjs+requirejs整合
- 6+重建二叉树
- 霍夫变换
- 【图论】[二分图匹配] 模板
- 【图论】[ZOJ1054]Place the Robots
- C语言(6)--国际象棋棋盘、螺旋矩阵、指定年份日历、打印ASCII码表
- Ajax提高篇(7)Ajax实现简单的下拉框联动显示数据
- C++中的指针和指针的引用
- 【图论】[ZOJ1002]Fire Net
- 如何理解file‘s owner
- 安装Android Studio结束时提示VT is not enabled in the system
- java stopwatch 功能
- URAL 1009 K-based Numbers dp练习