1001 Inversion
题意:求逆序对,然后交换k次相邻的两个数,使得剩下的逆序对最少。
分析:题目用到的结论是:数组中存在一对逆序对,那么可以通过交换相邻两个数使得逆序对减少1,交换k次,可以最多减少k个。
嘉定ai>aj,i < j,如果ai,aj相邻的,那么显然可以通过交换减少1;不相邻的情况,
考虑ak,k = j-1;
#11:ak > aj,那么ak,aj构成逆序对,交换后逆序对减少1;
#12:ak<=aj,那么ai,ak构成逆序对,问题转化为更小规模,可以通过同样的方法进一步分析,最终一定能够交换一次使得逆序对减少1个;
考虑ak,k = i+1;
#21:ak<ai,那么ai,ak构成逆序对,可以交换;
#22:ak>=ai那么ak,aj构成逆序对,问题规模缩小,和#12同样的处理方法。
所以最终答案就是max(0LL, ans-k)嘛,
代码:
分治法
1 //Template updates date: 20140718 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define inf 0x3f3f3f3f 20 #define pi acos(-1.0) 21 #define pb push_back 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 #define lowbit(x) (x&(-x)) 25 #define mp(a, b) make_pair((a), (b)) 26 #define bit(k) (1<<(k)) 27 #define iin freopen("pow.in", "r", stdin); 28 #define oout freopen("pow.out", "w", stdout); 29 #define in freopen("solve_in.txt", "r", stdin); 30 #define out freopen("solve_out.txt", "w", stdout); 31 #define bug puts("********))))))"); 32 #define Inout iin oout 33 #define inout in out 34 35 #define SET(a, v) memset(a, (v), sizeof(a)) 36 #define SORT(a) sort((a).begin(), (a).end()) 37 #define REV(a) reverse((a).begin(), (a).end()) 38 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 39 #define REP(i, n) for(int i = 0; i < (n); i++) 40 #define VREP(i, n, base) for(int i = (n); i >= (base); i--) 41 #define Rep(i, base, n) for(int i = (base); i < (n); i++) 42 #define REPS(s, i) for(int i = 0; (s)[i]; i++) 43 #define pf(x) ((x)*(x)) 44 #define mod(n) ((n)) 45 #define Log(a, b) (log((double)b)/log((double)a)) 46 #define Srand() srand((int)time(0)) 47 #define random(number) (rand()%number) 48 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 49 50 using namespace std; 51 typedef long long LL; 52 typedef unsigned long long ULL; 53 typedef vector<LL> VI; 54 typedef pair<int,int> PII; 55 typedef vector<PII> VII; 56 typedef vector<PII, int> VIII; 57 typedef VI:: iterator IT; 58 typedef map<string, int> Mps; 59 typedef map<int, int> Mpi; 60 typedef map<int, PII> Mpii; 61 typedef map<PII, int> Mpiii; 62 const int maxn = 100000 + 100; 63 int a[maxn]; 64 int n, k; 65 LL ans; 66 int T[maxn]; 67 68 void solve(int l, int r) { 69 if(l == r || l > r) 70 return; 71 int m = l+(r-l)/2; 72 solve(l, m); 73 solve(m+1, r); 74 int p = l, q = m+1; 75 int cnt = 0; 76 while(p <= m || q <= r) { 77 if(p > m|| (q <= r && a[q] < a[p])) 78 T[cnt++] = a[q++]; 79 else { 80 ans = ans + (q-m-1); 81 T[cnt++] = a[p++]; 82 } 83 } 84 REP(i, cnt) 85 a[l+i] = T[i]; 86 } 87 int main() { 88 89 while(scanf("%d%d", &n, &k) == 2) { 90 ans = 0; 91 Rep(i, 1, n+1) scanf("%d", a+i); 92 solve(1, n); 93 cout<<max(0LL, ans-k)<<endl; 94 } 95 return 0; 96 }
树状数组写法:
1 //Template updates date: 20140718 2 #include <iostream> 3 #include <sstream> 4 #include <cstdio> 5 #include <climits> 6 #include <ctime> 7 #include <cctype> 8 #include <cstring> 9 #include <cstdlib> 10 #include <string> 11 #include <stack> 12 #include <set> 13 #include <map> 14 #include <cmath> 15 #include <vector> 16 #include <queue> 17 #include <algorithm> 18 #define esp 1e-6 19 #define inf 0x3f3f3f3f 20 #define pi acos(-1.0) 21 #define pb push_back 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 #define lowbit(x) (x&(-x)) 25 #define mp(a, b) make_pair((a), (b)) 26 #define bit(k) (1<<(k)) 27 #define iin freopen("pow.in", "r", stdin); 28 #define oout freopen("pow.out", "w", stdout); 29 #define in freopen("solve_in.txt", "r", stdin); 30 #define out freopen("solve_out.txt", "w", stdout); 31 #define bug puts("********))))))"); 32 #define Inout iin oout 33 #define inout in out 34 35 #define SET(a, v) memset(a, (v), sizeof(a)) 36 #define SORT(a) sort((a).begin(), (a).end()) 37 #define REV(a) reverse((a).begin(), (a).end()) 38 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 39 #define REP(i, n) for(int i = 0; i < (n); i++) 40 #define VREP(i, n, base) for(int i = (n); i >= (base); i--) 41 #define Rep(i, base, n) for(int i = (base); i < (n); i++) 42 #define REPS(s, i) for(int i = 0; (s)[i]; i++) 43 #define pf(x) ((x)*(x)) 44 #define mod(n) ((n)) 45 #define Log(a, b) (log((double)b)/log((double)a)) 46 #define Srand() srand((int)time(0)) 47 #define random(number) (rand()%number) 48 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 49 50 using namespace std; 51 typedef long long LL; 52 typedef unsigned long long ULL; 53 typedef vector<LL> VI; 54 typedef pair<int,int> PII; 55 typedef vector<PII> VII; 56 typedef vector<PII, int> VIII; 57 typedef VI:: iterator IT; 58 typedef map<string, int> Mps; 59 typedef map<int, int> Mpi; 60 typedef map<int, PII> Mpii; 61 typedef map<PII, int> Mpiii; 62 const int maxn = 100000 + 100; 63 int a[maxn]; 64 int r[maxn], pos[maxn]; 65 int n, k; 66 LL sum[maxn]; 67 bool cmp(int v1, int v2) { 68 return a[v1] < a[v2] || (a[v1] == a[v2] && v1 < v2); 69 } 70 void update(int x) { 71 while(x <= n) { 72 sum[x] += 1; 73 x += lowbit(x); 74 } 75 } 76 LL getsum(int x) { 77 LL ans = 0; 78 while(x > 0) { 79 ans += sum[x]; 80 x -= lowbit(x); 81 } 82 return ans; 83 } 84 int main() { 85 86 while(scanf("%d%d", &n, &k) == 2) { 87 Rep(i, 1, n+1) scanf("%d", a+i), r[i] = i, sum[i] = 0; 88 sort(r+1, r+n+1, cmp); 89 Rep(i, 1, n+1) 90 pos[r[i]] = i; 91 LL ans = 0; 92 Rep(i, 1, n+1) { 93 update(r[i]); 94 ans += i-getsum(r[i]); 95 } 96 cout<<max(0LL, ans-k)<<endl; 97 } 98 return 0; 99 }
1004 Linear recursive sequence
题意:根据公式求指定某一项
题解分析在这里。
http://www.cnblogs.com/rootial/p/3920599.html
1007 Permutation
题意:给定n个数(n<=40),以及m种关系即第ai个数必须小于第bi个数,求这样的排列有多少个?
分析:m种关系显然构成一个拓扑图,且各个连通图之间互相独立,因此单个考虑每个连通图的可能性,比如一个连通图中有k个点,
从n个数中任选k个数,然后求这个图中能有多少个安排方案满足拓扑关系。
研究标程,具体实现是,通过并查集找出连通关系,(话说一直没这么用过,还想着去dfs求,弱菜),然后重新编号,通过cover[i] 表示从点i出发的能到达的点,先用于i有直接变得点初始化,然后floyd求连通性。
具体dp时,转移时这样的,dp[st|1<<i] += dp[st], st 满足(st&1<<i) == 0 && (st&cover[i]) == cover[i].
代码:
1009 Exclusive or
题意 :求f(n) = Sum{i^(n-i)| 1<=i <= n-1}.
分析:
此题关键在于对奇数和偶数分开求递推公式。
若n为偶数,设n = 2*k, 1<=i <= 2*k-1,分别考虑i为奇数和i为偶数时的值。
f(n) = i为奇数时+i为偶数 = sum{(2*i-1)^(n-(2*i-1))| 1<= i <= k} + sum{(2*i)^(n-2*i)| 1 <= i <= k-1}
= sum{(2*i-1)^(2*k-2*i+1)|1<=i <=k} + sum{(2*i)^(2*(k-i))| 1 <= i <= k-1}
= sum{(2*(i-1))^(2*(k-i))|1<= i <= k} + 2*sum{i^(k-i)| 1 <= i <= k-1}
= 2*sum{(i-1)^(k-i)|1<= i <= k} + 2*f(k)
= 2*sum{(i-1)^(k-1-(i-1)) | 1 <= i <= k} + 2*f(k)
= 2*sum{i^(k-1-i) | 0 <= i <= k-1} + 2*f(k)
= 2*f(k-1)+2*f(k)+4*k-4
若n为奇数,令n = 2*k+1, 1 <= i <= 2*k, 同样分析可得f(n) = 4*f(k) + 6*k.
然后利用大数算出即可。
代码:
1 #pragma comment(linker, "/STACK:167772160") 2 #include <cstdio> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cstdlib> 7 #include <algorithm> 8 #include <vector> 9 #include <queue> 10 #include <map> 11 #include <set> 12 #define in freopen("solve_in.txt", "r", stdin); 13 #define Rep(i, base, n) for(int i = (base); i < n; i++) 14 #define REP(i, n) for(int i = 0; i < (n); i++) 15 #define REPS(s, i) for(int i = 0; (s)[i]; i++) 16 #define VREP(i, n, base) for(int i = (n); i >= (base); i--) 17 #define SET(a, n) memset(a, (n), sizeof(a)); 18 #define pb push_back 19 #define mp make_pair 20 21 using namespace std; 22 typedef vector<unsigned short> VI; 23 typedef pair<unsigned short, unsigned short> PII; 24 typedef vector<PII> VII; 25 typedef long long LL; 26 const int maxn = 500; 27 const int B = 10000; 28 29 struct BigInt { 30 int dig[maxn], len; 31 BigInt(int num = 0):len(!!num) { 32 memset(dig, 0, sizeof dig); 33 dig[0] = num; 34 } 35 int operator[] (int index)const { 36 return dig[index]; 37 } 38 int& operator[] (int index) { 39 return dig[index]; 40 } 41 BigInt normalize() { 42 while(len && dig[len-1] == 0) 43 len--; 44 return *this; 45 } 46 void output() { 47 if(len == 0) { 48 cout<<0<<endl; 49 return; 50 } 51 printf("%d", dig[len-1]); 52 for(int i = len-2; i >= 0; i--) 53 printf("%04d", dig[i]); 54 cout<<endl; 55 } 56 }; 57 bool operator < (const BigInt &a, const BigInt &b) { 58 if(a.len != b.len) return a.len < b.len; 59 for(int i = a.len-1; i >= 0; i--) if(a[i] != b[i]) 60 return a[i] < b[i]; 61 return false; 62 } 63 BigInt operator + (const BigInt &a, const BigInt &b) { 64 BigInt c; 65 c.len = max(a.len, b.len)+1; 66 for(int i = 0, delta = 0; i < c.len; i++) { 67 delta += a[i]+b[i]; 68 c[i] = delta%B; 69 delta /= B; 70 } 71 return c.normalize(); 72 } 73 BigInt operator - (const BigInt &a, const int &b) { 74 BigInt c; 75 c.len = a.len; 76 for(int i = 0, delta = -b; i < c.len; i++) { 77 delta += a[i]; 78 c[i] = delta; 79 delta = 0; 80 if(c[i] < 0) { 81 c[i] += B; 82 delta = -1; 83 } 84 } 85 return c.normalize(); 86 } 87 BigInt operator * (const BigInt &a, const BigInt &b) { 88 BigInt c; 89 c.len = a.len+b.len+1; 90 for(int i = 0; i < a.len; i++) 91 for(int j = 0, delta = 0; j <= b.len; j++) { 92 delta += a[i]*b[j]+c[i+j]; 93 c[i+j] = delta%B; 94 delta /= B; 95 } 96 return c.normalize(); 97 } 98 BigInt operator / (const BigInt &a, const int &b) { 99 BigInt c; 100 c.len = a.len; 101 for(int i = a.len-1, delta = 0; i >= 0; i--) { 102 delta = a[i] + delta*B; 103 c[i] = delta/b; 104 delta %= b; 105 } 106 return c.normalize(); 107 } 108 char s[1000]; 109 typedef map<BigInt, BigInt> MPS; 110 MPS mps; 111 112 BigInt solve(BigInt n) { 113 BigInt nn; 114 nn = n/2; 115 // n.output(); 116 // nn.output(); 117 if(!mps.count(n)) { 118 if(n[0]&1) { 119 mps[n] = solve(nn)*4 + nn*6; 120 } else { 121 mps[n] = solve(nn-1)*2+solve(nn)*2+nn*4-4; 122 } 123 } 124 return mps[n]; 125 } 126 int tmp[] = {1, 10, 100, 1000}; 127 128 int main() { 129 130 mps[2] = 0; 131 mps[1] = 0; 132 mps[3] = 6; 133 mps[0] = 0; 134 while(scanf("%s", s) == 1) { 135 BigInt x; 136 int len = strlen(s); 137 reverse(s, s+len); 138 for(int i = 0; i < len; i++) { 139 int id = i/4+1; 140 x.len = max(x.len, id); 141 x[id-1] = x[id-1] + (s[i]-'0')*tmp[i%4]; 142 } 143 solve(x).output(); 144 } 145 return 0; 146 }
1010 Matrix multiplication
题意: 2个n*n的矩阵,输出相乘后每个元素对3取模后矩阵。
分析:输入时对每个元素取模,则剩下1*1,1*2,2*1,2*2这几种相乘情况,利用bitset,将相应的为1,2 的元素单独拿出来考虑,然后按照上面4种情况,分别求出相乘后的结果,最后加起来取模。
ADD:学习了一下bitset位集的使用。
代码:
1 #include <iostream> 2 #include <bitset> 3 #include <cstdio> 4 #define in freopen("solve_in.txt", "r", stdin); 5 6 using namespace std; 7 const int maxn =810; 8 bitset<maxn> b[2][2][maxn]; 9 int n; 10 11 int main() { 12 13 while(~scanf("%d", &n)) { 14 for(int k = 0; k < 2; k++) 15 for(int i = 0; i < n; i++) 16 for(int j = 0; j < n; j++) { 17 int t; 18 scanf("%d", &t); 19 t %= 3; 20 if(k == 1) { 21 b[k][0][j][i] = b[k][1][j][i] = 0; 22 if(t == 1) 23 b[k][0][j][i] = 1; 24 else if(t == 2) 25 b[k][1][j][i] = 1; 26 } else { 27 b[k][0][i][j] = b[k][1][i][j] = 0; 28 if(t == 1) 29 b[k][0][i][j] = 1; 30 else if(t == 2) 31 b[k][1][i][j] = 1; 32 } 33 } 34 for(int i = 0; i < n; i++) 35 for(int j = 0; j < n; j++) { 36 int t1 = (b[0][0][i]&b[1][0][j]).count(); 37 int t2 = (b[0][0][i]&b[1][1][j]).count()*2; 38 int t3 = (b[0][1][i]&b[1][0][j]).count()*2; 39 int t4 = (b[0][1][i]&b[1][1][j]).count(); 40 int ans = (t1+t2+t3+t4)%3; 41 printf("%d%c", ans, j == n-1 ? ' ' : ' '); 42 } 43 } 44 return 0; 45 }