noip模拟25[random·string·queen]
noip模拟25\;solutions
还是wzz的,依旧无法做出,勉勉强强的第一题拿了70pts,感觉自己菜到家了
啥也不会,啥也推不出来。。。。
T1\;random
这个就是一个打表找规律的题,我首先打表打出来,一个序列中如果有n个逆序对,
那么他的总贡献就是$\frac{4}{3}n$,题解上是直接统计的一个长为n的序列的总贡献
然后就继续打表,最后就得到了最后的$\huge\sum\limits_{i=1}^\frac{\frac{i(i-1)}{3}}$
为啥没拿满分呢,因为不会公式,然后考完之后一化简,直接输出$\frac{n^2-1}{9}$就好了
注意n,m超级大,先给他俩取个模
AC_code#include<bits/stdc++.h> using namespace std; #define ll long long const ll mod=998244353; ll T; ll ksm(ll x,ll y){ ll ret=1; while(y){ if(y&1)ret=ret*x%mod; x=x*x%mod; y>>=1; } return ret; } ll N; signed main(){ scanf("%lld",&T); while(T--){ scanf("%lld",&N); printf("%lld\n",((N%mod)*(N%mod)%mod-1+mod)%mod*ksm(9,mod-2)%mod); } }
T2\;string
这个就是暴力$hash$,考场上忘记$hash$咋写了,暴力取了个模,又WA又T的
所以我向$Varuxn$学习了$unsigned long long$不取模的做法,搞到了40pts
自己学习了题解部分分做法,搞到了$90pts$,虽然别人都只有$70pts$
虽然隔壁的Varuxn卡到了80,还是菜。。。。。。
咱也不知道为啥咱的暴力总是特别快,哈哈哈哈,咱就是牛逼,!!!!!!
90pts#include<bits/stdc++.h> using namespace std; #define re register int #define ull unsigned long long const int N=1e5+5; const ull bas=131; char s ,c[N*3]; int len ,n,sum; ull hs ,ba ,ans; vector<ull> ha ; ull f ,g ; signed main(){ scanf("%s",s+1); len[0]=strlen(s+1); for(re i=1;i<=len[0];i++) hs[i]=hs[i-1]*bas+s[i]-'a'; scanf("%d",&n); ba[0]=1;for(re i=1;i<N;i++)ba[i]=ba[i-1]*bas; for(re i=1;i<=n;i++){ scanf("%s",c+sum+1); len[i]=strlen(c+sum+1); //cout<<len[i]<<" "<<sum<<endl; ha[i].resize(len[i]+3); for(re j=sum+1;j<=len[i]+sum;j++) ha[i][j-sum]=ha[i][j-sum-1]*bas+c[j]-'a'; sum+=len[i]; } for(re x=1;x<=len[0];x++){ for(re i=1;i<=n;i++){ for(re l=1;l<=len[i];l++){ ull tmp0=hs[x+l-1]-hs[x-1]*ba[l]; ull tmp1=ha[i][l]; if(tmp0==tmp1)g[x]++; else break; } for(re r=1;r<=len[i];r++){ ull tmp0=hs[x]-hs[x-r]*ba[r]; ull tmp1=ha[i][len[i]]-ha[i][len[i]-r]*ba[r]; if(tmp0==tmp1)f[x]++; else break; } } } for(re i=1;i<len[0];i++)ans+=f[i]*g[i+1]; printf("%llu",ans); }
正解吧,把每个小串前缀后缀放到$Trie$上,开两个树,一个存前缀,一个存后缀
还有二分,我们枚举大串的每一个断点,向左右两侧寻找可以匹配的串的个数
这个时候就用到了$trie$,插入的时候,让走过的每一个节点的权值++
跑$dfs$,将每一个节点的权值,下放到儿子节点,顺便吧这个链的$hash$值求出来
将$hash$值和此时的权值放到$map$里,注意用$unordered_map$,这个还快一些
二分断点左右两侧能够匹配的长度,如果手写map的话可以$O(nlogn)$
我这个常数稍微大一些,注意用find函数,别直接用[]慢好多
AC_code#include<bits/stdc++.h> using namespace std; #define re register int #define ull unsigned long long const int N=1e5+5; const int bas=131; char s ,cc ; vector<char> c ; ull hs[2] ,ba ; ull f ,g ,ans; int len ,n; struct TRIE{ int siz[N*3],son[N*3][30]; int seg; unordered_map<ull,int> mp; TRIE(){seg=1;} void ins(int x,int i,int dep){ if(dep==c[i].size())return ; int w=c[i][dep]-'a'+1; if(!son[x][w])son[x][w]=++seg; siz[son[x][w]]++; ins(son[x][w],i,dep+1); } void dfs(int x,ull ha){ mp[ha]=siz[x]; //cout<<ha<<" "<<siz[x]<<endl; for(re i=1;i<=26;i++){ if(!son[x][i])continue; //cout<<x<<" "<<i<<" "<<ha*bas+i<<endl; siz[son[x][i]]+=siz[x]; dfs(son[x][i],ha*bas+i); } } }fro,beh; signed main(){ scanf("%s",s); len[0]=strlen(s); scanf("%d",&n); for(re i=1;i<=n;i++){ scanf("%s",cc+1); len[i]=strlen(cc+1); for(re j=1;j<=len[i];j++) c[i].push_back(cc[j]); } for(re i=1;i<=n;i++)fro.ins(1,i,0); for(re i=1;i<=n;i++)reverse(c[i].begin(),c[i].end()); for(re i=1;i<=n;i++)beh.ins(1,i,0); fro.dfs(1,0);beh.dfs(1,0); ba[0]=1; for(re i=1;i<=len[0];i++){ hs[0][i]=hs[0][i-1]*bas+s[i-1]-'a'+1; ba[i]=ba[i-1]*bas; } for(re i=len[0];i>=1;i--){ hs[1][i]=hs[1][i+1]*bas+s[i-1]-'a'+1; } for(re i=1;i<=len[0];i++){ /*for(re l=1;l<=len[0]-i+1;l++){ ull tmp=hs[0][i+l-1]-hs[0][i-1]*ba[l]; if(fro.mp[tmp])g[i]+=fro.mp[tmp]; else break; } for(re r=1;r<=i;r++){ ull tmp=hs[1][i-r+1]-hs[1][i+1]*ba[r]; if(beh.mp[tmp])f[i]+=beh.mp[tmp]; else break; }*/ ull res; int l=1,r=len[0]-i+1,mid; res=hs[0][i]-hs[0][i-1]*bas; if(fro.mp.find(res)==fro.mp.end())g[i]=0; else{ while(l<r){ mid=l+r+1>>1; ull tmp=hs[0][i+mid-1]-hs[0][i-1]*ba[mid]; if(fro.mp.find(tmp)!=fro.mp.end())l=mid; else r=mid-1; } res=hs[0][i+l-1]-hs[0][i-1]*ba[l]; g[i]=fro.mp[res]; } //cout<<i<<" "<<l<<" "; l=1;r=i; res=hs[1][i]-hs[1][i+1]*bas; if(beh.mp.find(res)==beh.mp.end())f[i]=0; else{ while(l<r){ mid=l+r+1>>1; ull tmp=hs[1][i-mid+1]-hs[1][i+1]*ba[mid]; if(beh.mp.find(tmp)!=beh.mp.end())l=mid; else r=mid-1; } res=hs[1][i-l+1]-hs[1][i+1]*ba[l]; f[i]=beh.mp[res]; //cout<<res<<" "<<l<<" "<<endl; //cout<<res<<" "<<l<<endl; } } for(re i=1;i<len[0];i++)ans+=f[i]*g[i+1];//cout<<f[i]<<" "<<g[i]<<endl; printf("%llu",ans); }
T3\;queen
就这,就这,就这啊!!!!
我没压行,而且吧,还把一行拆成两行了,你们不需要缩放页面!!!!
就推个式子,简简单单轻轻松松,题解说的挺明白,你要是想拍啊
就把代码粘走???
AC_code(缩放80%)#include<bits/stdc++.h> using namespace std; #define re register int #define ll long long const int mod=3e5+7; ll T,n,m,k,ans; ll jc[mod+10],inv[mod+10]; ll ksm(ll x,ll y){ ll ret=1; x%=mod; while(y){ if(y&1)ret=ret*x%mod; x=x*x%mod; y>>=1; } return ret; } ll W(ll x,ll y){ if(x<y)return 0; //cout<<inv[y]%mod*inv[(x-y+mod)%mod]%mod<<" "<<ksm(jc[y]*jc[(x-y+mod)%mod]%mod,mod-2)<<endl; return jc[x]*inv[y]%mod*inv[(x-y+mod)%mod]%mod; //return jc[x]*ksm(jc[y]*jc[(x-y+mod)%mod]%mod,mod-2)%mod; } ll C(ll x,ll y){ if(x<y)return 0; if(!x||!y)return 1; return C(x/mod,y/mod)*W(x%mod,y%mod)%mod; } signed main(){ jc[0]=1;inv[0]=1; for(re i=1;i<=mod;i++)jc[i]=jc[i-1]*i%mod; inv[mod-1]=ksm(jc[mod-1],mod-2); for(re i=mod-2;i>=1;i--)inv[i]=inv[i+1]*(i+1)%mod; scanf("%lld",&T); while(T--){ ans=0; scanf("%lld%lld%lld",&n,&m,&k); ans=(ans+(m%mod)*C(n,k)%mod)%mod; ans=(ans+(n%mod)*C(m,k)%mod)%mod; ll nn=max(n,m),mm=min(n,m); ans=(ans+2*(C(mm+1,k+1)*2+max(nn-mm-1,0ll)%mod*C(mm,k))%mod)%mod; if(n==m)ans=(ans+2*mod-2*C(m,k))%mod; if(k==1)ans=(n%mod)*(m%mod)%mod; if(k==3){ ll mi=min(n-1,(m-1)/2); //cout<<ans<<endl; ans=(ans+2*((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-(m+2*n)%mod*((mi%mod)*((mi+1)%mod))%mod*ksm(2,mod-2)%mod +ksm(3,mod-2)*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; swap(m,n); mi=min(n-1,(m-1)/2); //cout<<ans<<endl; ans=(ans+2*((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-(m+2*n)%mod*((mi%mod)*((mi+1)%mod))%mod*ksm(2,mod-2)%mod +ksm(3,mod-2)*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; swap(m,n); //cout<<ans<<endl; mi=min(n-1,m-1); ans=(ans+4*((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-((m+n)%mod)*(mi%mod)%mod*((mi+1)%mod)%mod*ksm(2,mod-2)%mod +ksm(6,mod-2)*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; } if(k==4){ ll mi=min(n-1,(m-1)/2); //cout<<ans<<endl; ans=(ans+2*((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-(m+2*n)%mod*((mi%mod)*((mi+1)%mod))%mod*ksm(2,mod-2)%mod +ksm(3,mod-2)*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; swap(m,n); mi=min(n-1,(m-1)/2); //cout<<ans<<endl; ans=(ans+2*((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-(m+2*n)%mod*((mi%mod)*((mi+1)%mod))%mod*ksm(2,mod-2)%mod +ksm(3,mod-2)*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; mi=min((m-1)/2,(n-1)/2); ans=(ans+5*((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-(2*(m+n)%mod)*(mi%mod)%mod*((mi+1)%mod)%mod*ksm(2,mod-2)%mod +4*ksm(6,mod-2)%mod*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; mi=min(n-1,m-1); ans=(ans+((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-((m+n)%mod)*(mi%mod)%mod*((mi+1)%mod)%mod*ksm(2,mod-2)%mod +ksm(6,mod-2)*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; } if(k==5){ ll mi=min((m-1)/2,(n-1)/2); ans=(ans+2*((n%mod)*(m%mod)%mod*(mi%mod)%mod+mod-(2*(m+n)%mod)*(mi%mod)%mod*((mi+1)%mod)%mod*ksm(2,mod-2)%mod +4*ksm(6,mod-2)%mod*(mi%mod)%mod*((mi+1)%mod)%mod*((mi*2+1)%mod)%mod)%mod)%mod; } printf("%lld\n",ans); } }
- 【2016.10.6NOIP普及模拟】Queen
- NOIP模拟10.5 T2
- [NOIP模拟][二分]cut
- JZOJ5397. 【NOIP2017提高A组模拟10.6】Biology
- 【NOIP2012模拟10.20】友好数对
- jzoj5399 【NOIP2017提高A组模拟10.7】Confess
- NOIP2017 赛前模拟 7.24
- 【NOIP2016提高A组模拟9.17】数格子
- [NOIP2017模拟]Array
- 树形dp(人品问题NOIP17提高模拟训练3)
- NOIP2016年普及组模拟考试(9.3) 5.母亲的牛奶
- noip2011 玛雅游戏 大模拟
- 【NOIP模拟】整除
- 选数问题【NOIP2016提高A组模拟9.21】
- 【NOIP 模拟赛】平均数 涂色游戏 序列题解
- 【NOIP普及组模拟】DNA排序
- NOIP提高组A组7.8模拟总结
- {题解}[jzoj4798] 【NOIP2016提高A组模拟9.24】天使的分裂
- 10.16 NOIP模拟赛 期望斜率优化 + 模拟 + 状压
- JZOJ 3823. 【NOIP2014模拟9.9】遇见