【簡要題解】洛谷 7 月月賽 Div.1
阿新 • • 發佈:2020-07-26
【簡要題解】洛谷 7 月月賽 Div.1
P6687 論如何玩轉 Excel 表格
把兩個狀態的每偶數列上下交換一下,旋轉操作就變成鄰項交換了。
//@winlere #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<vector> #include<map> #include<unordered_map> using namespace std; typedef long long ll; int qr(){ int ret=0,c=getchar(),f=0; while(!isdigit(c)) f|=c==45,c=getchar(); while( isdigit(c)) ret=ret*10+c-48,c=getchar(); return f?-ret:ret; } const int maxn=1e6+5; int a[2][maxn],b[2][maxn],id; vector< pair<int,int> > A,B; unordered_map< ll, int > qwq; int seg[maxn],data[maxn],n; void add(int pos,int val){ for(int t=pos;t<=n;t+=t&-t) seg[t]+=val; } int que(int pos){ int ret=0; for(int t=pos;t>0;t-=t&-t) ret+=seg[t]; return ret; } int main(){ n=qr(); for(int t=0;t<2;++t) for(int i=1;i<=n;++i) a[t][i]=qr(); for(int t=0;t<2;++t) for(int i=1;i<=n;++i) b[t][i]=qr(); for(int t=1;t<=n;++t){ if(t&1) A.push_back({a[0][t],a[1][t]}); else A.push_back({a[1][t],a[0][t]}); if(t&1) B.push_back({b[0][t],b[1][t]}); else B.push_back({b[1][t],b[0][t]}); } qwq.reserve(n<<1); for(int t=1;t<=n;++t) qwq[((ll)B[t-1].first<<30)+B[t-1].second]=t; for(int t=1;t<=n;++t){ auto g=qwq.find(((ll)A[t-1].first<<30)+A[t-1].second); if(g==qwq.end()) return puts("dldsgay!!1"),0; data[t]=g->second; } ll ans=0; for(int t=1;t<=n;++t) ans+=t-1ll-que(data[t]),add(data[t],1); printf("%lld\n",ans); return 0; }
P6688 可重集
將數字\(i\)變成\(x^{a_i}\),設\(F(l,r)=\sum_{i\in[l,r]}x^{a_i}\)。判斷兩個是否本質相同變成了判斷\(F(l,r)=F(L,R)\times x^{\min(l,r)-\min(L,R)}\),雜湊下就行。注意到種子要比\(a_i\)大
三哈,二哈,單哈都可以過
//@winlere #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; typedef long long ll; int qr(){ int ret=0,c=getchar(),f=0; while(!isdigit(c)) f|=c==45,c=getchar(); while( isdigit(c)) ret=ret*10+c-48,c=getchar(); return f?-ret:ret; } const int maxn=1e6+5; const ll mod1=1e18+3; const ll mod2=207132529660813483ll; const ll mod3=14285714285715727ll; const ll seed1=19260817; const ll seed2=19491001; const ll seed3=9137669; typedef ll E; ll MOD1(const ll&a){return a>=mod1?a-mod1:a;} ll MOD1(const ll&a,const ll&b){return (__int128)a*b%mod1;} E mi[maxn],seed(seed1); int a[maxn],n,m; namespace QWQ{ #define mid ((l+r)>>1) #define lef l,mid,pos<<1 #define rgt mid+1,r,pos<<1|1 int seg[maxn<<2]; E f[maxn<<2]; void pp(int pos){seg[pos]=min(seg[pos<<1],seg[pos<<1|1]);f[pos]=MOD1(f[pos<<1]+f[pos<<1|1]);} void build(int l,int r,int pos){ if(l==r) return seg[pos]=a[l],f[pos]=mi[a[l]],void(); build(lef); build(rgt); pp(pos); } void upd(int p,int v,int l,int r,int pos){ if(p<l||p>r) return; if(l==r) return seg[pos]=v,f[pos]=mi[v],void(); if(p<=mid) upd(p,v,lef); else upd(p,v,rgt); pp(pos); } pair<int,E> que(int L,int R,int l,int r,int pos){ if(L>r||R<l) return {1e9,0}; if(L<=l&&r<=R) return {seg[pos],f[pos]}; auto t1=que(L,R,lef),t2=que(L,R,rgt); return {min(t1.first,t2.first),MOD1(t1.second+t2.second)}; } #undef mid #undef lef #undef rgt } int main(){ n=qr(),m=qr(); mi[0]={1}; for(int t=1;t<=1e6;++t) mi[t]=MOD1(mi[t-1],seed); for(int t=1;t<=n;++t) a[t]=qr(); QWQ::build(1,n,1); for(int t=1;t<=m;++t){ int op=qr(); if(op==0){ int x=qr(),y=qr(); QWQ::upd(x,y,1,n,1); } if(op==1){ int l=qr(),r=qr(),L=qr(),R=qr(); auto LL=QWQ::que(l,r,1,n,1),RR=QWQ::que(L,R,1,n,1); E t1=LL.second,t2=RR.second; int TT1=LL.first,TT2=RR.first; if(TT1>TT2) t2=MOD1(t2,mi[TT1-TT2]); if(TT1<TT2) t1=MOD1(t1,mi[TT2-TT1]); if(t1==t2) puts("YES"); else puts("NO"); } } return 0; }
P6689 序列
任何一個有\(i\)個右括號的括號序列被那個演算法生成的概率是一樣的,先設\(dp(i,j)\)表示已經填了\(i\)個括號其中\(j\)個是左括號的概率。
轉移是
\[dp(i,j)={n-i+1\over n}dp(i-1,j-1)+\sum_{j=i}^n { j\times (j-1)\times (j-2)\dots \times i=j^{\underline {j-i+1}} \over n^{j-i+2}}(n-i+1) \]
可以簡單做到\(O(n^2)\)
現在還少一個東西,那就是一個有\(f_j=j\)個右括號的長度為\(n\)的括號序列期望有多少匹配(括號匹配指方案數是卡特蘭數那種匹配)數,列舉一對括號匹配在哪個地方並且產生一的貢獻,可以發現這一對括號匹配之間必須完美匹配,方案數是卡特蘭數。
\[f_j=\sum_{i=2}^n \sum_{j=0}^{\lfloor{i-2\over 2}\rfloor} C_j {n-2j-2\choose t-1-j}= \sum_{j=0}^{\lfloor{n-2\over 2}\rfloor} C_j (n-(2j-2)+1){n-2j-2\choose t-1-j} \]
複雜度\(O(n^2)\)
//@winlere
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<initializer_list>
using namespace std; typedef long long ll;
int qr(){
int ret=0,c=getchar(),f=0;
while(!isdigit(c)) f|=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=5015;
const int mod=998244353;
int jc[maxn<<1],inv[maxn<<1],invc[maxn<<1],dp[maxn][maxn],f[maxn<<1],temp[maxn],mi[maxn];
int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
int MOD(const int&x){return x>=mod?x-mod:x;}
int MOD(const initializer_list<int>&ve){int ret=1;for(auto t:ve) ret=MOD(ret,t); return ret;}
int ksm(const int&ba,const int&p){
int ret=1;
for(int t=p,b=ba;t;t>>=1,b=MOD(b,b))
if(t&1) ret=MOD(ret,b);
return ret;
}
void pre(const int&n){
jc[0]=inv[0]=1; jc[1]=inv[1]=invc[1]=1;
for(int t=2;t<=n;++t) jc[t]=MOD(jc[t-1],t),invc[t]=MOD(invc[mod%t],mod-mod/t),inv[t]=MOD(inv[t-1],invc[t]);
}
int c(const int&n,const int&m){return n<m||m<0?0:MOD(jc[n],MOD(inv[n-m],inv[m]));}
int cat(int n){return MOD(c(2*n,n),invc[n+1]);}
int main(){
pre(1e4+5);
int n=qr(),k=qr();
dp[0][0]=1; mi[0]=1;
for(int t=1;t<=n+5;++t) mi[t]=MOD(mi[t-1],invc[n]);
for(int t=1;t<=k;++t){
for(int i=n;i;--i) temp[i]=MOD(MOD({dp[t-1][i],jc[i],mi[i+2]})+temp[i+1]);
for(int i=1,g=n;i<=n;++i,g=MOD(g,n)){
int ret=0;
ret=MOD(ret+MOD({dp[t-1][i-1],n-i+1,invc[n]}));
ret=MOD(ret+MOD({temp[i],n-i+1,g,inv[i-1]}));
dp[t][i]=ret;
}
}
int ans=0;
for(int t=0;t<=n;++t){
int ret=0;
for(int j=0;j<=n/2-1;++j){
int sav=MOD({cat(j),n-2*j-1,c(n-2*j-2,t-1-j)});
ret=MOD(ret+sav);
}
ans=MOD(ans+MOD({inv[n],jc[t],jc[n-t],dp[k][t],ret,2}));
}
printf("%d\n",ans);
return 0;
}
P6690 一次函式
你覺得我會?