http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=690
A题:
给定字符串,求任意区间的Hash值。
根据题目给定的Hash方式,属于乘法类型,那么就可以预处理出所有的乘法前缀,然后利用逆元,就可以得到任意区间的Hash值。
不过在这题上跪了好久,最后讨论版的一位大神给出了一个很叼的隐含条件:“同志们,当a, b超范围的时候,输出上一次询问的答案,亲测可行。。。太坑了。。。”
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #include <set> #include <string> #include <vector> #define MOD 9973 using namespace std; const int maxN = 1000005; int q, len, ans, inv[10000], s[maxN]; char str[maxN]; void init() { //***预处理所有i在质数MOD下的逆元 inv[1] = 1; for (int i = 2; i < 10000; i++) inv[i] = inv[MOD%i]*(MOD-MOD/i) % MOD; } void input() { scanf("%s", str); len = strlen(str); for (int i = 0; i < len; ++i) { if (i == 0) s[i] = (str[i]-28+MOD)%MOD; else s[i] = s[i-1]*(str[i]-28+MOD)%MOD; } } bool judge(int lt, int rt) { if (lt > rt) return false; if (lt < 1 || lt > len) return false; if (rt < 1 || rt > len) return false; return true; } inline int getHash(int from, int to) { return (from == 0 ? s[to] : s[to]*inv[s[from-1]]%MOD); } void work() { int lt, rt; for (int i = 0; i < q; ++i) { scanf("%d%d", <, &rt); if (judge(lt, rt)) ans = getHash(lt-1, rt-1); printf("%d ", ans); } } int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); init(); while (scanf("%d", &q) != EOF) { input(); work(); } return 0; }
B题:
一个递推,如果有n个1,那么要么前两个1结合,要么不结合,那么p(n) = p(n-1)+p(n-2)。然后Java大数直接打表。
代码:
import java.math.BigInteger; import java.util.Scanner; public class Main { BigInteger p[] = new BigInteger[205]; void init() { p[1] = new BigInteger("1"); p[2] = new BigInteger("2"); for (int i = 3; i < 205; ++i) p[i] = p[i-1].add(p[i-2]); } public static void main(String[] args) { Scanner input = new Scanner(System.in); Main ans = new Main(); int n = 0; ans.init(); while (input.hasNext()) { n = input.nextInt(); System.out.println(ans.p[n]); } } }
C题:
一道字符串前缀问题。
有三种操作,插入一个单词,删除给定前缀的所有单词,查询是否存在给定前缀的单词。
用字典树搞,插入的时候,给路径上所有结点的vis加1。
删除的时候,删除前缀后面的所有子树,并将路径上所有结点的vis值,减去最末结点的vis值。
查询时,一旦路径上有一个vis值为0,就查询失败。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #include <set> #include <string> #include <vector> using namespace std; struct Trie { int vis; int next[26]; }tree[3000005]; int q, top; void build() { top = 0; for (int i = 0; i < 26; ++i) tree[0].next[i] = -1; tree[0].vis = 0; } int createNode() { top++; for (int i = 0; i < 26; ++i) tree[top].next[i] = -1; tree[top].vis = 0; return top; } void add(char str[]) { int len = strlen(str), k, now = 0; for (int i = 0; i < len; ++i) { k = str[i]-'a'; if (tree[now].next[k] == -1) tree[now].next[k] = createNode(); now = tree[now].next[k]; tree[now].vis++; } } void del(char str[]) { int len = strlen(str), k, now = 0, cnt; for (int i = 0; i < len; ++i) { k = str[i]-'a'; if (tree[now].next[k] == -1) return; now = tree[now].next[k]; } for (int i = 0; i < 26; ++i) tree[now].next[i] = -1; cnt = tree[now].vis; now = 0; for (int i = 0; i < len; ++i) { k = str[i]-'a'; now = tree[now].next[k]; tree[now].vis -= cnt; } } bool get(char str[]) { int len = strlen(str), k, now = 0; for (int i = 0; i < len; ++i) { k = str[i]-'a'; if (tree[now].next[k] == -1) return false; now = tree[now].next[k]; if (!tree[now].vis) return false; } return true; } void work() { build(); char op[20], str[40]; for (int i = 0; i < q; ++i) { scanf("%s%s", op, str); switch (op[0]) { case 'i': add(str); break; case 'd': del(str); break; case 's': if (get(str)) printf("Yes "); else printf("No "); break; } } } int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); while (scanf("%d", &q) != EOF) work(); return 0; }
D题:
这题直接排序+map能过。没试字典树。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #include <set> #include <string> #include <vector> using namespace std; int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int n; char str[50]; while (scanf("%d", &n) != EOF) { map<string, int> s; for (int i = 0; i < n; ++i) { scanf("%s", str); sort(str, str+strlen(str)); printf("%d ", s[str]++); } } return 0; }