來了。又是越考越差的時段。
和昨天是一個出題人,心態先崩一半。
$T1$有了點部分分剩下的還是沒有。依然沒有構造。依然出現原題($T3$是倉鼠雜題2)
然後比昨天還毒瘤的是今天連大樣例都沒了。
今天把聯考的排行榜粘過來以彰顯自己有多菜。
今天主要是時間分配掛了。
$T1$寫了三小時半多,$T2$用了$17min$,$T3$用了$10min$。然後瀏覽器被$oj$卡死提交用了$20min$。剩下時間在摸魚(放棄掙扎
$T1$最後會正解了但是來不及細想了(因爲$T2,3$暴力沒打)所以剩下$20$分不要就不要了。
考場上大規模幹$T1$就是腦子有問題。(大分類討論玩得挺歡?
$T2$寫了個亂搞本來能過$50$然後因爲分配的時間太少寫着急了有一個細節掛掉直接就爆零了。(我還以爲樣例不水)
全世界都沒幾個爆零的。。。
$T3$原題數學題。沒時間了所以打暴力跑路了。結果居然是全場$AC$數最多的題。。
什麼亂七八糟的。。。
T1:多邊形
大意:求正$n$邊形選$m$點構成的多邊形恰有$k$銳角的方案數。$n$是奇數。$n \le 10^6,T \le 10^5$
$k>3$無解。
考慮:多邊形外角和爲$360$。一個銳角對應一個$>90$的外角,故最多$3$個。
我們抽象一下問題:我們要選擇$m$個點$1 \le a_1 <a_2 < ... <a_m <n$。滿足恰有$k$個$i$滿足$a_{i+2}-a_i > \frac{n}{2}$
(序列是循環的,也就是$a_{m+1}=a_1,a+{m+3}=a_2$)
考慮爲什麼:首先作出原多邊形的外接圓,一個你選定的多邊形的角$ABC$也就是一個圓周角,則它對應的圓心角是二倍圓周角。
圓周角是銳角所以圓心角小於平角。所以說$a \rightarrow C$這一段弧是一個優弧,至少跨過$\frac{n}{2}$個點。
爲了方便下面設$N=\frac{n}{2}$
$k=3$時一定是三角形。此時$m \neq$則無解。
首先三角形的確可能有解。不是三角形的話則需要有三個$i$滿足條件,至少有兩個$i$的奇偶性相同。
$a_i < a_{i+2} < a_{i+2x} < a_{i+2x+2}$。第$1,3$個小於號的跨度都是$N$。所以$a_{i+2x+2}-a_i>n$就直接非法了。
然後一定是三角形的話,我們固定其中一個點,枚舉第二個點的編號,發現第三個點可選位置數是等差數列。直接$O(1)$解決。
$k=2$的話滿足條件的兩個$i$相差一定是$1$如果差距更大的話可以同上得到總長過長而非法。
我們欽定其中一個$i=1,a_1=1$。計算此時的方案再通過旋轉得到其它所有方案。
我們去枚舉$a_4$是幾。總方案是$\sum\limits_{a_4=N+3}^{n} \binom{n-a_4}{m-4} (a_4-N-2)^2$
就是後邊的點隨便選,那個平方就是在$a_1,a_4$之間選擇$a_2,a_3$的方案數。
考慮組合含義優化:我們在$[N+2,n]$裏選擇$a_4$,$n-a_4$個元需裏選$m-2$個,再在$a_4-N-2$個元素裏可重複選兩個。
分類討論你可重複選的那兩個是否重複了:
重複那就是一共在$[N+2,n]$裏隨便選$m-3$個然後欽定其中第二個是$a_4$。方案一一對應。直接組合數。
不重複那就多選一個,考慮到順序問題還要乘$2$。
特殊處理$m=3$。這樣$k=2$就可以$O(1)$解決。
$k=1$的話我採用的方法是:計數所有多邊形的銳角個數和再減去$k \ge 2$的方案的貢獻。
所以我們再次欽定一個銳角$i=1,a_1=1$。
這回只需要枚舉$a_3 > N+1$。方案數就是$\binom{n-a_3}{m-3} (a_3-2)$
還是組合含義優化,分類討論$a_2 >N+1$與否,組合數加上組合數乘係數。
$k=0$的情況就是所有情況減去上邊這些情況。
總時間複雜度$O(n+T)$
1 #include<cstdio> 2 const int mod=1000109107,S=1000005; 3 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;} 4 int n,m,t,k,fac[S],inv[S]; 5 int C(int b,int t){return t<0||t>b?0:fac[b]*1ll*inv[t]%mod*inv[b-t]%mod;} 6 int cal3(int n,int m){return m==3?n*(n+1ll)*(2*n+1)/6%mod:0;} 7 int cal2(int n,int m){ 8 if(m==3)return (mod+C(n+n+1,3)-cal3(n,m))%mod; 9 return (2ll*C(n,m-1)+C(n,m-2))*(1ll+n+n)%mod; 10 } 11 int cal1(int n,int m){ 12 int ans=(C(n,m-2)*1ll*n+C(n,m-1))%mod; 13 return ((ans*(1ll+n+n)-2*cal2(n,m)%mod-3ll*cal3(n,m))%mod+mod)%mod; 14 } 15 int main(){ 16 for(int i=fac[0]=1;i<S;++i)fac[i]=fac[i-1]*1ll*i%mod; 17 inv[S-1]=qp(fac[S-1],mod-2); 18 for(int i=S-2;~i;--i)inv[i]=inv[i+1]*(i+1ll)%mod; 19 scanf("%d",&t);while(t--){ 20 scanf("%d%d%d",&n,&m,&k); 21 n>>=1; 22 if(k>3)puts("0"); 23 else if(k==3)printf("%d\n",cal3(n,m)); 24 else if(k==2)printf("%d\n",cal2(n,m)); 25 else if(k==1)printf("%d\n",cal1(n,m)); 26 else printf("%lld\n",(mod*3ll+C(n+n+1,m)-cal1(n,m)-cal2(n,m)-cal3(n,m))%mod); 27 } 28 }
T2:仙人掌
大意:樹,每次操作會使某個點所有鄰居權值$+1$並詢問所有鄰居權值異或和。$n,Q \le 5 \times 10^5$
每次$+1$的話那麼子樹裏所有節點的權值最多有$O(\sqrt{m})$種。
所以直接開一個$unordered-set$暴力維護子樹中所有點的權值及出現次數,複雜度$O(n\sqrt{n})$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define f1 first 4 #define s2 second 5 const int mod=1000109107,S=1000005; 6 int n,m,ans,fir[S],l[S],to[S],ec,f[S],ts[S],tf[S]; 7 unordered_map<int,int>M[S],R; 8 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;} 9 void dfs(int p,int fa){ 10 f[p]=fa; M[fa][0]++; 11 for(int i=fir[p];i;i=l[i])if(to[i]!=fa)dfs(to[i],p); 12 } 13 int addson(int p){ 14 int a=0; 15 for(auto x:M[p])R[x.f1+1]=x.s2,a^=x.s2&1?x.f1+1:0; 16 swap(M[p],R);R.clear(); return a; 17 } 18 int addfa(int p){ 19 if(!p)return 0; 20 int a=tf[p]+ts[f[p]]; 21 int&x=M[f[p]][a];x--; if(!x)M[f[p]].erase(M[f[p]].find(a)); 22 M[f[p]][a+1]++; return a+1; 23 } 24 int main(){ 25 scanf("%d%d",&n,&m); 26 for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),link(a,b),link(b,a); 27 dfs(1,0); 28 for(int _=1,x;_<=m;++_) 29 scanf("%d",&x), 30 ans=(ans+(1ll*_*_+_)%mod*(addson(x)^addfa(f[x])))%mod, 31 ts[x]++,tf[f[x]]++; 32 printf("%d\n",ans); 33 }
正解是,發現一個數$+1$相當與異或上$2^{z+1}-1$。$z$是最低的$0$位。
按從低位到高位維護$trie$表示兒子的所有權值。每次跑$1$方向修改並更新答案。$O(nlogn)$
T3:多項式
大意:有$n$個$0 <x\le T$的變量和$m$個$0<x$的變量,其和$\le S$。求方案數。$n \le 10^9,m \le 10^3,nT \le S \le 10^{18},T \le 10^9$
首先爲了方便去掉$\le S$的限制所以我們可以新增一個不限制的變量,也就是說$m++$。爲了讓它也滿足$x>0$需要讓$S++$
可以列出這樣一個基礎式子$\sum\limits_{x_{1...n},\sum a =x} \binom{S-x}{m}$
組合數化成下降冪除階乘,階乘可以拿出來單算。然後我們有
$n^{\underline{m}} = \sum\limits_{i=0}^{m} (-1)^{m-i} \begin{bmatrix} m \\ i\end{bmatrix} n^i$
也就有我們要求的是$\frac{1}{m!} \sum\limits_{\sum a_i = x} \sum\limits_{i=0}^{m} \begin{bmatrix} m \\ i \end{bmatrix} (-1)^{m-i} (S-x)^i$
最後那個東西二項式展開一下
$\frac{1}{m!} \sum\limits_{\sum a_i = x} \sum\limits_{i=0}^{m} \begin{bmatrix} m \\ i \end{bmatrix} (-1)^{m-i} \sum\limits_{j=0}^{i} S^{i-j}(-1)^j x^j$
這樣就只有最後一項與$x$有關了。我們要求的形如下式:
$A_j = \sum\limits_{\sum\limits_{i=1}^{n} a_i = x} x^j$
設$F_{k,j} = \sum\limits_{\sum\limits_{i=1}^{k} a_i = x} x^j$
根據二項式展開那一套,有$F_{x+y,i+j} = \sum F_{x,i} F(y,j) \binom{i+j}{i}$
所以可以直接倍增$F$求出$A$。$F_{0,i}$就是簡單的自然數冪和。隨便怎麼做都行。
式子逐層處理即可。時間複雜度$O(m^2logn)$
1 #include<cstdio> 2 #define ll long long 3 const int mod=1000109107,S=1005; 4 int n,m,t,fac[S],ans,F[31][S],A[S],st[S][S],St[S][S],C[S][S],iv[S],G[S],pws[S];ll s; 5 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;} 6 int Spw(int n,int k,int a=0){for(int i=0,C=1+n;i<=k;++i)a=(a+1ll*St[k][i]*fac[i]%mod*C)%mod,C=1ll*C*(n-i)%mod*iv[i+2]%mod;return a;} 7 int main(){ 8 for(int i=fac[0]=iv[1]=1;i<S;++i)fac[i]=fac[i-1]*1ll*i%mod; 9 for(int i=2;i<S;++i)iv[i]=mod-mod/i*1ll*iv[mod%i]%mod; 10 for(int i=st[0][0]=St[0][0]=C[0][0]=1;i<S;++i)for(int j=C[i][0]=1;j<=i;++j) 11 st[i][j]=(st[i-1][j]*(i-1ll)+st[i-1][j-1])%mod, 12 St[i][j]=(St[i-1][j]*1ll*j+St[i-1][j-1])%mod, 13 C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 14 scanf("%lld%d%d%d",&s,&t,&n,&m); m-=n; s%=mod; 15 for(int i=0;i<=m;++i)F[0][i]=Spw(t,i); F[0][0]--; 16 for(int i=1;1<<i<=n;++i)for(int j=0;j<=m;++j)for(int k=0;k+j<=m;++k) 17 F[i][j+k]=(F[i][j+k]+1ll*F[i-1][j]*F[i-1][k]%mod*C[j+k][j])%mod; 18 for(int i=0;i<=30;++i)F[i][0]--; 19 A[0]=1; 20 for(int i=0;1<<i<=n;++i)if(n>>i&1)for(int j=m;~j;--j)for(int k=m-j;~k;--k) 21 A[j+k]=(A[j+k]+1ll*A[j]*F[i][k]%mod*C[j+k][j])%mod; 22 for(int i=pws[0]=1;i<=m;++i)pws[i]=pws[i-1]*1ll*s%mod; 23 for(int i=0;i<=m;++i)for(int j=0;j<=i;++j) 24 G[i]=(G[i]+(j&1?mod-1ll:1ll)*pws[i-j]%mod*A[j]%mod*C[i][j])%mod; 25 for(int i=0;i<=m;++i)ans=(ans+(m-i&1?mod-1ll:1ll)*st[m][i]%mod*G[i])%mod; 26 printf("%lld\n",ans*1ll*qp(fac[m],mod-2)%mod); 27 }