这里将本次资格赛的题目和解题报告放上来,自己也从中学习了复习了不少知识点,做题的感觉不错。
这题先打表算出第一个元素到第i个元素的所有值hash[i],所求是x,那么hash[left-1] * x %9973 = hash[right] % 9973,实际上就是解模线性方程模线性方程 a * x = b (% n)。x为正整数。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define maxn 100010
char szWords[maxn];
int dp[maxn];
int extgcd(int a, int b, int &x, int &y)
{
if (b == 0) { x = 1; y = 0; return a;}
int d = extgcd(b, a % b, x, y);
int t = x; x = y; y = t - a / b * y;
return d;
}
vector modeq(int a, int b, int n)
{
vector res;
int e, i, d, x, y;
d = extgcd(a, n, x, y);
if (b % d > 0) return res;
e = (x * (b / d)) % n;
for (i = 0; i < d; i++)
{
int ans = (e + i *(n / d)) % n;
res.push_back(ans);
}
return res;
}
int main()
{
//freopen("input.txt", "r", stdin);
int N;
while (scanf("%d", &N) != EOF)
{
/*getchar();
gets(szWords);*/
scanf("%s", szWords);
int len = strlen(szWords);
dp[0] = 1;
for (int i = 0; i < len; ++i)
{
dp[i+1] = dp[i] * ((int)szWords[i] - 28);
dp[i+1] %= 9973;
}
for (int i = 0; i < N; ++i)
{
int a, b;
scanf("%d %d", &a, &b);
vector res = modeq(dp[a-1], dp[b], 9973);
int ans = res[0];
if (ans < 0)
{
ans += 9973;
}
printf("%d\n", ans);
}
}
return 0;
}
简单递推,考虑dp[i],那么有两种情况,一种是i不与其他元素合并,有dp[i-1],另一种是一定与其他元素合并,有dp[i-2],即dp[i] = dp[i-1] + dp[i-2],斐波那契数列。
另外需要注意溢出的问题,C++用大数模板。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
const int base = 10000; // (base^2) fit into int
const int width = 4; // width = log base
const int N = 1000; // n * width: 可表示的最大位数
struct bint{
int ln, v[N];
bint (int r = 0) { // r 应该是字符串!
for (ln = 0; r > 0; r /= base) v[ln++] = r % base;
}
bint& operator = (const bint& r) {
memcpy(this, &r, (r.ln + 1) * sizeof(int));// !
return *this;
}
} ;
bint operator + (const bint& a, const bint& b){
bint res; int i, cy = 0;
for (i = 0; i < a.ln || i < b.ln || cy > 0; i++) {
if (i < a.ln) cy += a.v[i];
if (i < b.ln) cy += b.v[i];
res.v[i] = cy % base; cy /= base;
}
res.ln = i;
return res;
}
bool read(bint& b, char buf[]) // 读取失败返回0
{
//if (1 != scanf("%s", buf)) return 0;
int w, u, ln = strlen(buf);
memset(&b, 0, sizeof(bint));
if ('0' == buf[0] && 0 == buf[1]) return 1;
for (w = 1, u = 0; ln; ) {
u += (buf[--ln] - '0') * w;
if (w * 10 == base) {
b.v[b.ln++] = u; u = 0; w = 1;
}
else w *= 10;
}
if (w != 1) b.v[b.ln++] = u;
return 1;
}
void write(const bint& v){
int i;
printf("%d", v.ln == 0 ? 0 : v.v[v.ln - 1]);
for (i = v.ln - 2; i >= 0; i--)
printf("%04d", v.v[i]); // ! 4 == width
printf("\n");
}
bint num[210];
void InitAns()
{
read(num[1], "1");
read(num[2], "2");
for (int i = 3; i <= 200; ++i)
{
num[i] = num[i-2] + num[i-1];
}
}
int main()
{
//freopen("input.txt", "r", stdin);
InitAns();
int N;
while (scanf("%d", &N) != EOF)
{
write(num[N]);
}
return 0;
}
典型的字典树,纯模板,醉了。
#include
#include
#include
using namespace std;
#define maxnode 30
struct Node
{
char ch;
Node *next[maxnode];
int count;
Node()
{
count = 0;
memset(next, 0, sizeof(next));
}
};
void Destroy(Node *root)
{
if (!root) return;
for (int i = 0; i < maxnode; ++i)
{
Destroy(root->next[i]);
}
delete root;
}
void DestroySon(Node *root)
{
if (!root) return;
for (int i = 0; i < maxnode; ++i)
{
Destroy(root->next[i]);
root->next[i] = NULL;
}
}
void Insert(Node *root, char str[])
{
Node *cur = root;
for (int i = 0; str[i]; ++i)
{
int id = str[i] - 'a';
if (!cur->next[id]) cur->next[id] = new Node;
cur = cur->next[id];
++cur->count;
}
}
Node *Search(Node *root, char str[])
{
Node *cur = root;
for (int i = 0; str[i]; ++i)
{
int id = str[i] - 'a';
if (cur->next[id])
cur = cur->next[id];
else
return NULL;
}
return cur;
}
void Delete(Node *root, char str[])
{
Node *cur = Search(root, str);
if (!cur) return;
DestroySon(cur);
cur->count;
Node *pcur = root;
for (int i = 0; str[i]; ++i)
{
int id = str[i] - 'a';
if (pcur->next[id])
{
pcur = pcur->next[id];
pcur->count -= cur->count;
}
}
}
int main()
{
//freopen("input.txt", "r", stdin);
int N;
scanf("%d",&N);
Node *root = new Node;
for(int i = 0; i < N; ++i)
{
char op[32],s[32];
scanf("%s %s", op, s);
if(op[0] == 'i')
{
Insert(root, s);
}
else if(op[0] == 'd')
{
Delete(root, s);
}
else
{
Node *tmp = Search(root,s);
if (tmp && tmp->count > 0)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}
return 0;
}
没啥好说的,每个字符串排序一下,通过map记录count。
#include
#include
#include
#include
#include
#include
#include
#include
先说一下题目意思,不太好懂,就是每一行的每个变量表示一个集合,某个变量集合为空,那么说明整个语句集合都是空,否则各变量分别对应一个集合。另外,如果某一行没有某个变量,就认为这个变量范围是无穷,题目没有说清楚,不过第一行第二行能体现。
理解了题目意思,那么整个题目难度不算大,就是比较繁琐,算得上大模拟题吧。每行存多个集合,一个变量必须合并集合,为空就非法。字符串处理注意细节,思路清晰容易写。
#include
#include
#include
#include
using namespace std;
#define MAXNUM 10010
struct Gather
{
string varName;
int left, right;
Gather()
{
left = - MAXNUM;
right = MAXNUM;
}
};
vector Gathers[1010];
bool bLegal[1010];
void SkipSpace(const char *&sz)
{
while (*sz && (*sz == ' ' || *sz == ',')) ++sz;
}
bool GetMixedRange(int l1, int r1, int l2, int r2, int &l, int &r)
{
l = max(l1, l2);
r = min(r1, r2);
return l1 <= l2;
}
void AddtoGathers(int t, Gather obj)
{
for (int i = 0; i < Gathers[t].size(); ++i)
{
if (Gathers[t][i].varName == obj.varName)
{
// 合并变量
int l, r;
if (GetMixedRange(Gathers[t][i].left, Gathers[t][i].right,
obj.left, obj.right, l, r))
{
Gathers[t][i].left = l;
Gathers[t][i].right = r;
}
else
{
bLegal[t] = false;
}
return;
}
}
Gathers[t].push_back(obj);
}
bool JudgeFixed(const Gather &a, const Gather &b)
{
if (a.varName != b.varName) return true;
int l = max(a.left, b.left), r = min(a.right, b.right);
return l <= r;
}
void HandleGather(string str, int t)
{
const char *sz = str.c_str();
while (*sz)
{
string varName, oper;
int opNum = 0;
SkipSpace(sz);
// varName
while (isalpha(*sz))
{
varName += *sz;
++sz;
}
SkipSpace(sz);
// oper
while (*sz != ' ' && !isdigit(*sz))
{
oper += *sz;
++sz;
}
SkipSpace(sz);
// obNum
while (*sz && isdigit(*sz))
{
opNum = opNum * 10 + *sz - '0';
++sz;
}
Gather obj;
obj.varName = varName;
if (oper == "<")
{
obj.right = opNum - 1;
}
else if (oper == ">")
{
obj.left = opNum + 1;
}
else if (oper == "<=")
{
obj.right = opNum;
}
else if (oper == ">=")
{
obj.left = opNum;
}
else if (oper == "==")
{
obj.left = obj.right = opNum;
}
AddtoGathers(t, obj);
if (!bLegal[t])
{
printf("unique\n");
return;
}
}
// begin to judge
vector result;
for (int i = 0; i <= t - 1; ++i)
{
if (!bLegal[i]) continue;
bool ok = true;
for (int j = 0; j < Gathers[i].size(); ++j)
{
for (int k = 0; k < Gathers[t].size(); ++k)
{
if (!JudgeFixed(Gathers[i][j], Gathers[t][k]))
{
ok = false;
break;
}
}
if (!ok) break;
}
if (ok)
result.push_back(i+1);
}
if (result.empty())
{
printf("unique\n");
}
else
{
printf("%d", result[0]);
for (int i = 1; i < result.size(); ++i)
{
printf(" %d", result[i]);
}
printf("\n");
}
}
int main()
{
//freopen("input.txt", "r", stdin);
int N;
scanf("%d",&N);
for (int i = 0; i < N; ++i)
{
bLegal[i] = true;
}
string str;
getline(cin, str);
for(int i = 0; i < N; ++i)
{
getline(cin, str);
HandleGather(str, i);
}
return 0;
}