洛谷P3014 [USACO11FEB]牛线Cow Line
---恢复内容开始---
洛谷P3014 [USACO11FEB]牛线Cow Line
关于康托展开 与 康托逆展开
1 #include <bits/stdc++.h> 2 #define For(i, j, k) for(int i=j; i<=k; i++) 3 #define Dow(i, j, k) for(int i=j; i>=k; i--) 4 #define LL long long 5 using namespace std; 6 inline LL read() { 7 LL x = 0, f = 1; 8 char ch = getchar(); 9 while(ch<'0'||ch>'9') { if(ch=='-') f = -1; ch = getchar(); } 10 while(ch>='0'&&ch<='9') { x = x*10+ch-48; ch = getchar(); } 11 return x * f; 12 } 13 void write(LL x) { 14 if(x<0) putchar('-'), x = -x; 15 if(x>9) write(x/10); 16 putchar(x%10+48); 17 } 18 inline void writeln(LL x) { write(x); putchar('\n'); } 19 20 const int N = 30; 21 int n,Ques; 22 LL Fact[N]; 23 int vis[N]; 24 25 inline void calc(int n) { 26 Fact[0]=1; 27 For(i, 1, n) Fact[i]=Fact[i-1]*i; 28 } 29 30 inline int getpre(int n, int x) { 31 vis[x] = 1; 32 int res = 0; 33 For(i, 1, x-1) 34 if(!vis[i]) ++res; 35 return res; 36 } 37 38 inline void getprint(int n, LL x) { 39 int pos = 0; 40 For(i, 1, x+1) { 41 ++pos; 42 while(vis[pos] && pos<=n) ++pos; 43 } 44 vis[pos] = 1; 45 write(pos); putchar(' '); 46 } 47 48 int main() { 49 n = read(); Ques = read(); 50 calc(n); 51 while(Ques--) { 52 char s[10]; 53 scanf("%s",s+1); 54 if(s[1]=='Q') { 55 LL ans = 0; 56 For(i, 0, n) vis[i] = 0; 57 Dow(i, n, 1) { 58 int x = read(); 59 ans += getpre(n, x)*Fact[i-1]; // 这里可以用树状数组来优化 60 } 61 writeln(ans+1); 62 } 63 else { 64 For(i, 0, n) vis[i] = 0; 65 LL x = read(); x--; 66 Dow(i, n, 1) { 67 getprint(n, x/Fact[i-1]); 68 x %= Fact[i-1]; 69 } 70 puts(""); 71 } 72 } 73 return 0; 74 }
---恢复内容结束---