此处有
目录↑
第一次用结构体存储每个字符出现的个数,然后再用map,250ms左右
Problem A (前缀积&&乘法逆元)
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
本来第一反应就是想用前缀积+乘法逆元算的,结果非常倔强地相同线段树,就愉快地一直RE了,最终还是用了 前缀积+乘法逆元
后来才知道数据也有毒...
#include <cstdio>
#include <algorithm>
using namespace std;
const int MOD=9973;
char s[100005];
int n,num[100005],l,r;
int inv[9975];
void getInv() {
inv[0]=0;
inv[1]=1;
for(int i=2;i<MOD;++i) {
inv[i]=(inv[MOD%i]*(MOD-MOD/i))%MOD;
}
}
int main() {
getInv();
while(1==scanf("%d ",&n)) {
gets(s+1);
num[0]=1;
for(int i=1;s[i]!='\0';++i) {
num[i]=(num[i-1]*(s[i]-28))%MOD;
}
while(n-->0) {
scanf("%d%d",&l,&r);
if(l>r) {
swap(l,r);
}
printf("%d\n",(num[r]*inv[num[l-1]])%MOD);
}
}
return 0;
}
Problem B (DP)
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
设dp[i]表示长度为i的'1'串能构造出的序列个数
则第i个字符不与任何字符组合时,共dp[i-1]种新序列;第i个字符与第i-1个字符组合时,共dp[i-2]种新序列
则可得状态转移方程为:dp[i]=dp[i-1]+dp[i-2]
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LEN 110
#define MOD 100000000
using namespace std;
struct BigInt {
int len,p[LEN];
BigInt() {
memset(p,0,sizeof(p));
len=0;
}
}dp[205];
int n,t;
BigInt add(const BigInt& x,const BigInt& y) {
BigInt cnt;
t=max(x.len,y.len);
for(int i=1;i<=t;i++) {
cnt.p[i]+=x.p[i]+y.p[i];
cnt.p[i+1]=cnt.p[i]/MOD;
cnt.p[i]%=MOD;
}
if(cnt.p[t+1])
t++;
cnt.len=t;
return cnt;
}
void print(const BigInt& x) {
printf("%d",x.p[x.len]);
for(int i=x.len-1;i>=1;i--)
printf("%08d",x.p[i]);
printf("\n");
}
int main() {
dp[0].p[1]=1;
dp[0].len=1;
dp[1].p[1]=1;
dp[1].len=1;
for(int i=2;i<=204;++i) {
dp[i]=add(dp[i-1],dp[i-2]);
}
while(scanf("%d",&n)==1) {
print(dp[n]);
}
return 0;
}
Problem C (Trie树)
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
第一反应就是在插入新单词时,给路径上的每个节点都+1,然而倔强地想用isEnd表示单词的结束,又WA了好久,最后才发现删除时有问题。。。果断改回去就AC了
#include <cstdio>
using namespace std;
const int MAXN=3000005;
struct Trie {
int next[MAXN][26];
int num[MAXN];
int l;
const static int root=0;
Trie() {
clear();
}
int newNode() {
num[l]=0;
for(int i=0;i<26;++i) {
next[l][i]=-1;
}
return l++;
}
void insert(char *p) {
int cur=root;
while((*p)!='\0') {
if(next[cur][(*p)-'a']==-1) {
next[cur][(*p)-'a']=newNode();
}
cur=next[cur][(*p)-'a'];
++num[cur];
++p;
}
}
void delet(char *p,int cnt) {
int cur=root;
while((*p)!='\0') {
cur=next[cur][(*p)-'a'];
num[cur]-=cnt;
++p;
}
for(int i=0;i<26;++i) {
next[cur][i]=-1;
}
}
int query(char *p) {
int cur=root;
while((*p)!='\0') {
if(next[cur][(*p)-'a']==-1) {
return 0;
}
cur=next[cur][(*p)-'a'];
++p;
}
return num[cur];
}
void clear() {
l=root;
newNode();
}
}trie;
int main() {
int n;
char cmd[35],s[35];
scanf("%d",&n);
trie.clear();
while(n-->0) {
scanf("%s%s",cmd,s);
if(cmd[0]=='i') {
trie.insert(s);
}
else if(cmd[0]=='d') {
int cnt=trie.query(s);
if(cnt>0) {
trie.delet(s,cnt);
}
}
else {
printf("%s\n",trie.query(s)>0?"Yes":"No");
}
}
return 0;
}
Problem D (map)
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
第二次直接对排序后的string用map,460ms左右,看来stl真得少用
#include <iostream>
#include <cstring>
#include <string>
#include <map>
using namespace std;
struct Node {
int num[26];
bool operator < (const Node& a) const {
for(int i=0;i<26;++i) {
if(num[i]!=a.num[i]) {
return num[i]<a.num[i];
}
}
return false;
}
}cur;
int n;
map<Node,int> mp;
char s[45];
int main() {
cin.sync_with_stdio(false);
while(cin>>n) {
while(n-->0) {
cin>>s;
memset(cur.num,0,sizeof(cur.num));
for(int i=0;s[i]!='\0';++i) {
++cur.num[s[i]-'A'];
}
printf("%d\n",mp[cur]);
++mp[cur];
}
}
}
第五题感觉就是一道麻烦的模拟题,就不写了...