#91 E

problem link http://codeforces.com/contest/122/problem/E

Lucky number contains only 4s and/or 7s, find the amount of lucky number whose postion also a lucky number of the Kth permutation of a 10^9 long seqence sort lexicographically.

What a dam thing? Calm down to analyse, no big deal.

First thing to do is list all permutation of a small sequence lexicographically.

1 2 3 4  2 1 3 4  3 1 2 4  4 1 2 3

1 2 4 3  2 1 4 3  3 1 4 2  4 1 3 2

1 3 2 4  2 3 1 4  3 2 1 4  4 2 1 3

1 3 4 2  2 3 4 1  3 2 4 1  4 2 3 1

1 4 2 3  2 4 1 3  3 4 1 2  4 3 1 2

1 4 3 2  2 4 3 1  3 4 2 1  4 3 2 1

There is an obvious regulation of such order for permutation. when list a n-permutation for such order, the first (n-1)! permutation don't affect the position of first element.

Delving a little deeper, the first (n-j)! permutation only affect the positions of the last n-j elements.

Back to the problem, the Kth permutation while K ranges from 1 to 10^9, and  13! < 10^9 < 14!, so that means at most last 14 numbers. and the rest (at most 10^9 - 14 ) will stay where they are.

For these unmoved numbers, I just need to check whether it is a lucky number, but 10^9-14 still too big to enumerate, so I just need to construct all lucky numbers small than 10^9. Anyway, these part of the problem has been solved, so enter into the most confusing part -- how to know the situation of the Kth permutation of the at most last 14 numbers.

Look at the above sample permutations again. The first number of all permutation is ordered lexicographically, if I divide these permutations into n groups ( n = 4 in the sample ), each group's size is (n-1)!, then the same regulation will appear again in each group, and I can do that recursively.

Okay, I got it, just give me K, according to K I can find the pair (p, q) that p! < K < q!, and then only the last q numbers will be rearranged in permutations, and then:

g1 = (int)(K / (q-1)!) is the group order for the frist number in Kth permutation. 

K = K - g1 * (q-1)! is the postion of the second number in these group.

g2 = (int)(K / (q-2)!) is the group order for the second number in Kth permutation.

K = K - g2 * (q-2 )! is the postion of the third number in these group.

and so on until (q-q)!. 

Note, gi isn't the number in i position in Kth permutation, it just the group order, telling me to pick the gi-th number in the remaining numbers on the i-th position, and remove it from the remaining numbers, every number can only takes on one position.

Using this algorithm, I can construct the K-th permutation, after that, just find all numbers on lucky positions, and check whether that number is also a lucky number.

#include <stdio.h>

long long permu[14];
bool is_used[14];
int permu_pos[14];
long long lucks[2000];
int luck_cnt;

int main() {
long long i,j,k;
int N,K,p1,p2,t1,t2,t3,m=1e9;
permu[0] = 1;
for( i=1;i<14;i++ ) {
permu[i] = 1;
for( j=1,k=1;j<=i;j++ )
permu[i]*=j;
}

luck_cnt = 0;
lucks[luck_cnt++] = 4;
lucks[luck_cnt++] = 7;
for( i=0;true;i++ ) {
lucks[luck_cnt++] = lucks[i] * 10 + 4;
if( lucks[luck_cnt-1] >= m )
break;
lucks[luck_cnt++] = lucks[i] * 10 + 7;
if( lucks[luck_cnt-1] >= m )
break;
}

/*for( i=0;i<14;i++ ) {
printf("%lld\n", permu[i]);
}
printf("\n");
*/

scanf("%d %d", &N, &K);

p1 = N > 13 ? N - 13 : 0;
p2 = N > 13 ? p1 + 1 : 1;

j = N-p1;
if( (long long)K > permu[j] ) {
printf("-1\n");
return 0;
}

for( i=j-1;i>=0;i-- ) {
// if the string to permu length 13, then the group size is (13-1)!
t1 = (((long long)K + permu[i] - 1) / permu[i]);
for( k=1,t2=0;t2<t1;k++ )
if( !is_used[k] ) t2++;

// loop end. t2 == t1;
permu_pos[j-i] = k-1;
is_used[k-1] = true;
K -= (t1-1) * permu[i];
}

/*for( i=1;i<=(N-p1);i++ )
printf("%d ", permu_pos[i]);
printf("\n");
*/

for( i=0;lucks[i] <= p1;i++ ) ;
t3 = i;

for( i=1;i<=N-p1;i++ ) {
t1 = permu_pos[i] + p1;
t2 = i + p1;
for( j=0,k=0;j<luck_cnt && k<2;j++ ) {
if( t1 == lucks[j] )
k++;
if( t2 == lucks[j] )
k++;
}
if( k==2 )
t3++;
}

printf("%d\n", t3);

return 0;
}



你可能感兴趣的:(#)