題目比較基礎。java
A題:node
算字符串連續子串的hash,線段樹維護hash,這裏並非標準的hash,因此沒難度。ios
固然用前綴和+逆元好像也能夠,不過我沒想清楚若是被除數爲0怎麼處理逆元。ide
#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; const ll MOD=9973; ll H[maxn<<2]; int n; char s[maxn];int len; int L,R; void push_up(int rt) { H[rt]=(H[rt<<1]*H[rt<<1|1])%MOD; } void build(int l,int r,int rt) { if(l==r){ H[rt]=(s[l]+MOD-28)%MOD; return; } int m=(l+r)>>1; build(lson); build(rson); push_up(rt); } ll query(int L,int R,int l,int r,int rt) { if(L>R) return 0; //cout<<"L="<<L<<" R="<<R<<" l="<<l<<" r="<<r<<" rt="<<rt<<" Hrt="<<H[rt]<<endl; if(L<=l&&r<=R) return H[rt]; int m=(l+r)>>1; ll res=1; if(L<=m) res=(res*query(L,R,lson))%MOD; if(R>m) res=(res*query(L,R,rson))%MOD; return res; } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d",&n)){ scanf("%s",s+1); len=strlen(s+1); build(1,len,1); while(n--){ scanf("%d%d",&L,&R); printf("%I64d\n",query(L,R,1,len,1)); } } return 0; }
B題:ui
設前i個的方案數爲f[i],那麼第i個要麼和前一個合併,方案數爲f[i-2],要麼不合並,方案數爲f[i-1],因此f[i]=f[i-1]+f[i-2]。spa
因爲斐波那契數列是指數級的,因此第200個確定爆了longlong,須要模擬大數加法,或者直接用java。code
#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef unsigned long long ll; const int maxn=1000100; const int INF=1e9+10; int n; string s[210]; string add(string a,string b) { string c=""; int la=a.size(),lb=b.size(); int tag=0; if(la>lb) swap(la,lb),swap(a,b); //cout<<"a="<<a<<" b="<<b<<endl; REP(i,0,la-1){ int t=a[i]-'0'+b[i]-'0'+tag; c+=(char)(t%10+'0'); tag=t/10; } REP(i,la,lb-1){ int t=b[i]-'0'+tag; c+=(char)(t%10+'0'); tag=t/10; } if(tag) c+=(char)(tag+'0'); //cout<<"c="<<c<<endl; return c; } void Init() { s[0]=s[1]="1"; REP(i,2,201) s[i]=add(s[i-1],s[i-2]); } int main() { //freopen("in.txt","r",stdin); Init(); while(~scanf("%d",&n)){ if(n<=0) puts(""); else{ for(int i=s[n].size()-1;i>=0;i--) printf("%c",s[n][i]);puts(""); } } return 0; }
C題:blog
很基礎的trie,直接維護個數sz,模擬插入刪除就能夠了,每次修改通過路徑的值,刪除結點的時候不用內存池回收,空間是夠用的。內存
#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef unsigned long long ll; const int maxn=3000100; const int INF=1e9+10; struct Trie { int ch[maxn][26]; int rt,tot; int sz[maxn]; int newnode() { ++tot; MS0(ch[tot]); sz[tot]=0; return tot; } void init() { tot=0; rt=newnode(); } void insert(char *s) { int len=strlen(s); int u=rt; REP(i,0,len-1){ int c=s[i]-'a'; if(!ch[u][c]) ch[u][c]=newnode(); sz[ch[u][c]]++; u=ch[u][c]; } } void del(char *s) { int len=strlen(s); int u=rt; REP(i,0,len-1){ int c=s[i]-'a'; if(!ch[u][c]) return; u=ch[u][c]; } int t=sz[u]; u=rt; REP(i,0,len-1){ int c=s[i]-'a'; u=ch[u][c]; sz[u]-=t; } REP(c,0,25) ch[u][c]=0; } bool find(char *s) { int len=strlen(s); int u=rt; REP(i,0,len-1){ int c=s[i]-'a'; if(!ch[u][c]) return 0; u=ch[u][c]; } return sz[u]!=0; } };Trie tr; int n; char op[maxn],s[maxn]; int main() { while(cin>>n){ tr.init(); REP(i,1,n){ scanf("%s%s",op,s); if(op[0]=='i') tr.insert(s); else if(op[0]=='d') tr.del(s); else puts(tr.find(s)?"Yes":"No"); } } return 0; }
D題:ci
map記錄一下出現次數就能夠了。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<string> #include<map> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; int n; string s; map<string,int> cnt; int main() { while(cin>>n){ cnt.clear(); REP(i,1,n){ cin>>s; sort(s.begin(),s.end()); printf("%d\n",cnt[s]); cnt[s]++; } } return 0; }
E題:
因爲變量只有30個,因此將每一個條件每一個變量的解集初始化爲[-INF,INF],而後讀入條件,和前面的暴力判斷一下交集就能夠了。
主要是讀入的過程,算是不太麻煩的小模擬。
#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<map> #include<string> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef unsigned long long ll; const int maxn=3000100; const int INF=1e9+10; int cn; struct Node { int L[40],R[40]; bool kong; };Node a[maxn]; map<string,int> id; int n; char s[maxn]; int main() { freopen("in.txt","r",stdin); while(cin>>n){ id.clear(); REP(i,1,n) REP(j,1,30) a[i].L[j]=-INF,a[i].R[j]=INF,a[i].kong=0; cn=0; gets(s); //cout<<"s="<<s<<endl; REP(i,1,n){ gets(s); int len=strlen(s); //cout<<"s="<<s<<endl; for(int j=0;j<len;){ while(j<len&&s[j]==' ') j++; string name=""; while(j<len&&s[j]!=' ') name+=s[j++]; while(j<len&&s[j]==' ') j++; string p=""; while(j<len&&s[j]!=' ') p+=s[j++]; while(j<len&&s[j]==' ') j++; int num=0; int ttt=1; if(s[j]=='-') ttt=-1,j++; while(j<len&&s[j]!=' ') num=num*10+s[j]-'0',j++; while(j<len&&s[j]==' ') j++; while(j<len&&s[j]==',') j++; num*=ttt; if(!id[name]) id[name]=++cn; int x=id[name]; if(p=="<") a[i].R[x]=min(a[i].R[x],num-1); else if(p=="<=") a[i].R[x]=min(a[i].R[x],num); else if(p==">") a[i].L[x]=max(a[i].L[x],num+1); else if(p==">=") a[i].L[x]=max(a[i].L[x],num); else if(p=="==") a[i].L[x]=max(a[i].L[x],num),a[i].R[x]=min(a[i].R[x],num); //cout<<"j="<<j<<" len="<<len<<endl; } REP(j,1,30) if(a[i].L[j]>a[i].R[j]) a[i].kong=1; vector<int> ans; REP(j,1,i-1){ if(a[j].kong||a[i].kong) continue; bool has=1; REP(k,1,30){ if(a[i].L[k]>a[j].R[k]||a[j].L[k]>a[i].R[k]){ has=0;break; } } if(has) ans.push_back(j); } if(a[i].kong||(int)ans.size()==0) puts("unique"); else{ for(int j=0;j<ans.size();j++){ printf("%d",ans[j]); if(j!=(int)ans.size()-1) printf(" "); else printf("\n"); } } } //REP(i,1,cn) cout<<a[3].L[i]<<" "<<a[3].R[i]<<" "<<a[3].kong<<endl; } return 0; }