hihoCoder太阁最新面经算法竞赛19

时间:2022-11-24 15:20:44

比赛链接:http://hihocoder.com/contest/hihointerview28/problems

A. 固定一个方向,两两相邻的点顺时针或逆时针构造三个向量,判断这个点在这个向量的左侧还是右侧,看看是否在同一侧。trick就是点在向量上,对应的情况就是值为0.

 def do(p1x, p1y, p2x, p2y, p3x, p3y):
return (p3x - p1x) * (p2y - p1y) - (p2x - p1x) * (p3y - p1y); T = map(int, raw_input().split(' '))[0]
while T > 0:
T -= 1
px, py, ax, ay, bx, by, cx, cy = map(int, raw_input().split(' '))
x, y, z = do(ax, ay, px, py, bx, by), do(bx, by, px, py, cx, cy), do(cx, cy, px, py, ax, ay)
if (x >= 0 and y >= 0 and z >= 0) or (x <= 0 and y <= 0 and z <= 0):
print 'YES'
else:
print 'NO'

B.打表规律,发现<=16的时候可以暴搜,>16的时候f(n)=4*f(n-5)(?如果没记错的话),矩阵加速一下就行了。

 #include <bits/stdc++.h>
using namespace std; typedef long long LL;
const LL mod = 1000000007LL;
const int maxn = ;
LL n;
LL ret; typedef struct Matrix {
LL m[maxn][maxn];
int r;
int c;
Matrix() {
r = c = ;
memset(m, , sizeof(m));
}
} Matrix; Matrix mul(Matrix m1, Matrix m2, LL mod) {
Matrix ans = Matrix();
ans.r = m1.r;
ans.c = m2.c;
for(int i = ; i <= m1.r; i++) {
for(int j = ; j <= m2.r; j++) {
for(int k = ; k <= m2.c; k++) {
if(m2.m[j][k] == ) continue;
ans.m[i][k] = ((ans.m[i][k] + m1.m[i][j] * m2.m[j][k] % mod) % mod) % mod;
}
}
}
return ans;
} Matrix quickmul(Matrix m, LL n, LL mod) {
Matrix ans = Matrix();
for(int i = ; i <= m.r; i++) {
ans.m[i][i] = ;
}
ans.r = m.r;
ans.c = m.c;
while(n) {
if(n & ) {
ans = mul(m, ans, mod);
}
m = mul(m, m, mod);
n >>= ;
}
return ans;
} void dfs(LL n, LL cur, LL sz) {
if(n == ) {
ret = max(ret, cur);
return;
}
if(n >= ) dfs(n-,cur*%mod, cur);
if(n >= && sz) dfs(n-, (cur+sz)%mod, sz);
dfs(n-,(cur+)%mod, sz);
} int main() {
// freopen("in", "r", stdin);
while(cin >> n) {
if(n < ) {
ret = ;
dfs(n, , );
cout << ret << endl;
continue;
}
Matrix x; x.r = , x.c = ;
x.m[][] = , x.m[][] = , x.m[][] = , x.m[][] = , x.m[][] = ;
Matrix p; p.r = p.c = ;
memset(p.m, , sizeof(p.m));
p.m[][] = ;
for(int i = ; i <= ; i++) p.m[i][i-] = ;
p = quickmul(p, n-, mod);
p = mul(p, x, mod);
cout << p.m[][] << endl;
}
return ;
}

C.对于trie上的每个节点u,求最小的整数x满足 节点u对应的字符串(trie上root->u的路径) 是 S[1..x]的子序列。

 #include <bits/stdc++.h>
using namespace std; const int maxn = ;
const int maxm = ;
const int maxc = ; typedef pair<int, int> pii;
typedef struct Trie {
int rt, sz;
int id[maxm][maxc], val[maxm];
int dp[maxm];
string s;
void build() {
rt = sz = ;
memset(dp, , sizeof(dp));
memset(id, -, sizeof(id));
memset(val, , sizeof(val));
}
void insert(const char* str) {
int u = rt;
int n = strlen(str);
for(int i = ; i < n; i++) {
int v = str[i] - 'a';
if(id[u][v] == -) id[u][v] = ++sz;
u = id[u][v];
}
val[u] = max(val[u], n);
}
void dfs(int x, int u) {
if(x == s.length()) return;
for(int i = ; i < ; i++) {
int &v = id[u][i];
if(v == -) continue;
int y = x;
while(s[y] != i + 'a' && y < s.length()) y++;
if(y == s.length()) break;
if(i + 'a' == s[y]) {
dp[v] = dp[u] + ;
dfs(y+, v);
}
}
}
}Trie; int n;
char tmp[maxm];
Trie trie; int main() {
// freopen("in", "r", stdin);
while(~scanf("%d", &n)) {
trie.build();
for(int i = ; i < n; i++) {
scanf("%s", tmp);
trie.insert(tmp);
}
scanf("%s", tmp);
trie.s = tmp;
trie.dfs(, );
int ret = ;
for(int i = ; i <= trie.sz; i++) {
// printf("%d %d\n", trie.dp[i], trie.val[i]);
if(trie.dp[i] != ) {
ret = max(ret, trie.val[i]);
}
}
printf("%d\n", ret);
}
return ;
}