A. DNA Alignment
题意: 给定一个字符串s。 ……&(&(%……*&……)&*(&(*&%…………*%#%¥@¥*(%()
思路: 假设s和t中AGCT的出现次数为a,b,c,d和w,x,y,z次, 则h(s,t) = n * (a * w + b * x + c * y + d * z)。
所以, 如果n和abcd都是一定的话, 那么t中的字符一定要取出现次数最大的那个字符, 假设出现次数最大的字符有k个, 则答案就是k ^ n。
写java还是只能在水题装逼啊。。。。忧伤
import java.io.*;
import java.util.*;
import java.math.*;
public class Main {
public static int f(char c) {
switch(c) {
case 'A': return 0;
case 'G': return 1;
case 'C': return 2;
case 'T': return 3;
default: return 0;
}
}
static public void main(String []args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
String s = cin.next();
int len = s.length();
int cnt[] = new int[4];
for(int i = 0; i < len; ++i) {
cnt[f(s.charAt(i))]++;
}
int mx = 0, k = 0;
for(int i = 0; i < 4; ++i) {
if(cnt[i] > mx) {
mx = cnt[i];
k = 1;
}
else if(cnt[i] == mx)
++k;
}
long ans = 1;
for(int i = 1; i <= n; ++i)
ans = ans * k % 1000000007;
System.out.println(ans);
}
}
B. Cubes
题意: 给定二维平面上的n个点, 序号为0 ~ n - 1, 一个点能取出的条件为取出它后全部剩余点都是稳定的, 一个点(x, y)稳定的条件是y == 0 或者 (x - 1, y - 1) || (x, y - 1) || (x + 1, y - 1)存在, 有两个玩家A, B, A希望取出序列字典序尽量大, B希望取出序列字典序尽量小, 轮流取出点, A先, 问取出顺序转化成十进制是多少。
思路:先把图转化成有向图,并且记录反向图。 一个点如果它的上边3个方向有点, 就连边, 然后维护能取的点的大顶堆和小顶堆, 取大的的时候就从大顶堆取, 取小的时候就从小顶堆取。
刚开始入度为1的点, 它的前驱节点肯定是不能放进堆的, 其他的点就能, 取出一个点的时候, 要考虑两个情况, 一是取出它之后, 它的前驱节点会不会本来是不可取的变成可取的, 有这种情况的话要把前驱节点加入堆, 第二种情况就是取出它之后, 它的后继节点的前驱节点会不会本来可取的变成不可取的, 如果有这种情况的话要从堆中删掉那个变成不可取的点。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cstdlib>
using namespace std;
#define LL long long
#define inf 0x3f3f3f3f
#define eps 1e-8
#define ULL unsigned long long
#define mxn 100020
#define mxe 200020
#define mxnode 20020
#define mod 1000000009
#define vi vector<int>
#define pii pair<int, int>
#define vii vector<pii >
#define MP make_pair
#define PB push_back
vector<int> g[mxn], rg[mxn];
map<pii, int> mp;
int n;
int x[mxn], y[mxn];
int in[mxn], out[mxn];
priority_queue<int> maxQ;
priority_queue<int, vector<int>, greater<int> > minQ;
bool inq[mxn];
bool vis[mxn];
void init() {
fill(g, g + mxn, vector<int>());
fill(rg, rg + mxn, vector<int>());
memset(inq, 0, sizeof inq);
while(!maxQ.empty()) maxQ.pop();
while(!minQ.empty()) minQ.pop();
memset(inq, 1, sizeof inq);
memset(in, 0, sizeof in);
memset(out, 0, sizeof out);
memset(vis, 0, sizeof vis);
mp.clear();
}
void pushIt(int k) {
if(inq[k]) return;
inq[k] = 1;
maxQ.push(k);
minQ.push(k);
}
int getMin() {
while(!minQ.empty()) {
int u = minQ.top(); minQ.pop();
if(inq[u] == 0) continue;
inq[u] = 0;
return u;
}
}
int getMax() {
while(!maxQ.empty()) {
int u = maxQ.top(); maxQ.pop();
if(inq[u] == 0) continue;
inq[u] = 0;
return u;
}
}
LL qpow(LL x, int k) {
LL ret = 1;
while(k) {
if(k & 1) ret = ret * x % mod;
k >>= 1;
x = x * x % mod;
}
return ret;
}
int main() {
// freopen("tt.txt", "r", stdin);
while(scanf("%d", &n) != EOF) {
init();
for(int i = 0; i < n; ++i) {
scanf("%d%d", x + i, y + i);
mp[MP(x[i], y[i])] = i;
}
for(int i = 0; i < n; ++i) {
for(int d = -1; d <= 1; ++d) {
int dx = x[i] + d;
int dy = y[i] + 1;
if(mp.count(MP(dx, dy)) == 0) continue;
int v = mp[MP(dx, dy)];
g[i].PB(v);
rg[v].PB(i);
out[i]++, in[v]++;
}
}
for(int i = 0; i < n; ++i) {
if(in[i] == 1)
inq[rg[i][0]] = 0;
}
for(int i = 0; i < n; ++i)
if(inq[i] == 1) {
maxQ.push(i), minQ.push(i);
}
LL ans = 0;
int Lv = n - 1;
for(int i = 0; i < n; ++i, --Lv) {
int t;
if(i & 1)
t = getMin();
else
t = getMax();
// printf("%d\n", t);
ans = (ans + t * qpow(n, Lv)) % mod;
vis[t] = 1;
for(int j = 0; j < rg[t].size(); ++j) {
if(vis[rg[t][j]]) continue;
int p = rg[t][j];
out[p]--;
bool flag = 1;
for(int k = 0; k < g[p].size(); ++k) {
int v = g[p][k];
if(vis[v]) continue;
if(in[v] == 1)
flag = 0;
}
if(flag)
pushIt(p);
}
for(int j = 0; j < g[t].size(); ++j) {
int w = g[t][j];
if(vis[w]) continue;
in[w]--;
for(int k = 0; k < rg[w].size(); ++k) {
int u = rg[w][k];
if(vis[u]) continue;
if(in[w] == 1)
inq[u] = 0;
}
}
}
printf("%I64d\n", ans);
}
return 0;
}