NOIP模擬「random·string·queen」
阿新 • • 發佈:2021-07-28
T1:random
我又來白剽部落格了:
詳細證明請看土哥
土哥寫的不是很詳細,我在這裡詳細寫一下:
首先,對於f[n]的式子:
加一是那一個對的貢獻,大C是選其餘的幾個數,\(2^{N}\)是總的子集個數。
逆序對的期望個數是:
首先,所有數字兩兩匹配,共有\(n*(n-1)\)對,,然後,某個對成為逆序對的的概率是50%,所以變成了四分之。
上程式碼:
#include<bits/stdc++.h> using namespace std; namespace STD { #define rr register #define inf INT_MAX typedef long long ll; const ll mod=998244353; ll n; ll read() { rr ll x_read=0,y_read=1; rr char c_read=getchar(); while(c_read<'0'||c_read>'9') { if(c_read=='-') y_read=-1; c_read=getchar(); } while(c_read<='9'&&c_read>='0') { x_read=(x_read<<3)+(x_read<<1)+(c_read^48); c_read=getchar(); } return x_read*y_read; } ll qpow(ll base,ll exp) { ll ret=1ll; while(exp) { if(exp&1) ret=ret*base%mod; base=1ll*base*base%mod; exp>>=1; } return ret; } }; using namespace STD; int main() { n=read(); ll inv=qpow(9,mod-2); for(rr int i=1;i<=n;i++) { ll x=read()%mod; cout<<(x*x%mod-1+mod)*inv%mod<<'\n'; } }
T2:string
氣死,這題我改了一整天,結果發現是二分與Hash表的指標打錯了,氣死。
這題的思路是Hash+Trie。
手寫Hash,快的一批。
注意字尾要倒著插,字首要正著插。
程式碼:
#include<bits/stdc++.h> using namespace std; namespace STD { #define rr register #define inf INT_MAX #define scanf ybbb=scanf typedef long long ll; typedef unsigned long long ull; const int N=1e5+4; const int LEN=2e5+4; const ull base=131; int m,ybbb; int pre[N],suc[N]; char s[N]=""; ull mi[N],has[N],rehas[N]; struct node { node * nxt; ull key; int sum; node() { key=sum=0; nxt=NULL; } node(ull key_,int sum_) { key=key_,sum=sum_; nxt=NULL; } }; class Hash { private: node * head[LEN]; public: void insert(ull,int); node * find(ull); }h[2]; void Hash::insert(ull key,int sum) { ull x=key%(LEN-4); if(head[x]==NULL) { head[x]=new node(key,sum); return ; } node * temp=head[x]; node * pre=NULL; while(temp!=NULL&&(temp->key!=key)) { pre=temp; temp=temp->nxt; } if(temp==NULL) { temp=new node(key,sum); if(pre!=NULL) pre->nxt=temp; return; } temp->sum=sum; } node * Hash::find(ull key) { ull x=key%(LEN-4); node * temp=head[x]; while(temp!=NULL&&temp->key!=key) temp=temp->nxt; return temp; } class Trie { private: int tot; int ch[LEN][28]; int cnt[LEN]; public: int sp; Trie(){tot=1;} void insert(char*,char*); void get(int,ull); }t[2]; void Trie::insert(char * st,char * en) { int p=1; if(st>=en) { for(rr char * i=st;i>=en;i--) { int x=(*i)-'a'+1; if(ch[p][x]==0) ch[p][x]=++tot; p=ch[p][x]; cnt[p]++; } } else { for(rr char * i=st;i<=en;i++) { int x=(*i)-'a'+1; if(ch[p][x]==0) ch[p][x]=++tot; p=ch[p][x]; cnt[p]++; } } } void Trie::get(int id,ull has) { for(rr int i=1;i<=26;i++) { if(ch[id][i]) { cnt[ch[id][i]]+=cnt[id]; h[sp].insert(has*base+i,cnt[ch[id][i]]); get(ch[id][i],has*base+i); } } } int read() { rr int x_read=0,y_read=1; rr char c_read=getchar(); while(c_read<'0'||c_read>'9') { if(c_read=='-') y_read=-1; c_read=getchar(); } while(c_read<='9'&&c_read>='0') { x_read=(x_read<<3)+(x_read<<1)+(c_read^48); c_read=getchar(); } return x_read*y_read; } void Pre() { mi[0]=1; for(rr int i=1;i<=N-2;i++) mi[i]=mi[i-1]*base; } inline ull substr(int l,int r){return has[r]-has[l-1]*mi[r-l+1];} inline ull resubstr(int l,int r){return rehas[l]-rehas[r+1]*mi[r-l+1];} }; using namespace STD; int main() { Pre(); scanf("%s",s+1); m=read(); for(rr int i=1;i<=m;i++) { char a[N]=""; scanf("%s",a+1); int len=strlen(a+1); t[0].insert(a+1,a+len); t[1].insert(a+len,a+1); } t[0].sp=0,t[1].sp=1; t[0].get(1,0),t[1].get(1,0); int len=strlen(s+1); for(rr int i=1;i<=len;i++) has[i]=has[i-1]*base+s[i]-'a'+1; for(rr int i=len;i>=1;i--) rehas[i]=rehas[i+1]*base+s[i]-'a'+1; //suc for(rr int i=1;i<=len;i++) { int l=1,r=i; while(l<r) { int mid=(l+r)>>1; ull x=resubstr(mid,i); node * temp=h[1].find(x); if(temp==NULL) l=mid+1; else r=mid; } ull x=resubstr(l,i); node * temp=h[1].find(x); if(temp!=NULL) suc[i]=temp->sum; } //pre for(rr int i=len;i>=1;i--) { int l=i,r=len; while(l<r) { int mid=(l+r+1)>>1; ull x=substr(i,mid); node * temp=h[0].find(x); if(temp==NULL) r=mid-1; else l=mid; } ull x=substr(i,l); node * temp=h[0].find(x); if(temp!=NULL) pre[i]=temp->sum; } ll ans=0; for(rr int i=1;i<len;i++) ans+=1ll*suc[i]*pre[i+1]; printf("%lld\n",ans); }
T3:queen
emmmm。。。。官方題解已經很詳細了,就不寫了,但是土哥給了兩個優化,還是很香的。
一個是對於\(\sum_{i=0}^{n}\)\(C^{m}_{i}\)=\(C^{m+1}_{n+1}\)的優化(證明是楊輝三角裂項)。
另一個是\(\sum_{i=1}^{n}\)\(i^{2}\)=\(n*(n+1)*(2*n+1)/6\)。
真的棒極了。