231113校内赛
T1 项链
首先一个求最大的最小就很容易想到二分
发现我们可以通过 \(\mathcal O(n)\) 来方便的求出如何删除,总时间复杂度只有 \(\mathcal O(n\log n)\)
因为这是一个环,我们需要特殊判断首尾相接时的状况
对于最后一个和第一个的比较一定只会删一次
证明如下:
\(a_1+a_2\le x\) 且 \(a_1+a_n > x\) 时
我们删去小的那个之后
如果 \(a_1 >a_n\) 显然 \(a_n+a_2 < x\)
如果 \(a_n \ge a_1\) 那么剩下的还是 \(a_1+a_2\) 仍然不可能再删
#include<bits/stdc++.h>
#define int long long
#define N 500010
using namespace std;
int n,m,tid,a[N],stk[N],top;
inline int check(int x){
top = 0;
for(int i = 1;i<=n;i++){
if(stk[top]+a[i]>x){
stk[top] = min(stk[top],a[i]);
continue;
}
stk[++top] = a[i];
}
if(stk[1]+stk[top]>x) top--;
return top;
}
signed main(){
freopen("necklace.in","r",stdin);
freopen("necklace.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>tid>>n>>m;
for(int i = 1;i<=n;i++)
cin>>a[i];
int l = 0,r = 2e9,ans = 2e9;
while(l<=r){
int mid = (l+r)>>1;
if(check(mid)<m) l = mid+1;
else r = mid-1,ans = mid;
}
cout<<ans;
return 0;
}
T2 计树
考虑 \(dp\) ,设 \(f_{i,j,k}\) 表示考虑了前 \(i\) 个节点,有 \(j\) 个节点没有父亲,即当前图为有 \(k\) 棵树的森林,且前 \(i\) 个点缺少 \(k\) 个儿子,转移时设第 \(i+1\) 个节点儿子数量为 \(l\)
分类讨论一下:
\(l = 0\) 时
-
如果新开一棵树:\(f_{i+1,j+1,k} = f_{i,j,k}\)
-
如果接在某个缺儿子的节点下面 \(f_{i+1,j,k} = k \times f_{i,j,k}\)
\(l = 1\) 时
和 \(l = 0\) 的转移方式一样,但两个转移时都要乘二,因为有左右儿子之分
\(l = 2\) 时
与 \(l=0\) 时相同,且有额外的两种方式
-
将某个没有父亲的节点接在它下面 \(f_{i+1,j,k+1}=2 \times j \times f_{i,j,k}\)
-
将某个没有父亲的节点接在它下面,并且它接在某个缺儿子的节点下面 \(f_{i+1,j-1,k} = 2\times (j-1)\times k \times f_{i,j,k}\) ,\(j-1\) 是因为你已经确定了哪个缺儿子的节点了,而这个节点就不能作为一个没有父亲的点接在你下面了
时间复杂度 \(\mathcal O(Tn^3)\)
#include<bits/stdc++.h>
#define int long long
#define N 310
#define mod ((int)1e9+7)
using namespace std;
int n,l[N],r[N],f[N][N][N];
int ksm(int x,int y){
int res = 1;
while(y){
if(y&1) res = res*x%mod;
x = x*x%mod;
y>>=1;
}
return res;
}
signed main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T,tid;cin>>tid>>T;
while(T--){
memset(f,0,sizeof(f));
cin>>n;
for(int i = 1;i<=n;i++)
cin>>l[i]>>r[i];
f[0][0][0] = 1;
for(int i = 1;i<=n;i++){
for(int j = 0;j<i;j++){
for(int k = 0;k<=n;k++){
if(!f[i-1][j][k]) continue;
if(l[i]==0){
f[i][j+1][k] = (f[i][j+1][k]+f[i-1][j][k])%mod;
if(k) f[i][j][k-1] = (f[i][j][k-1]+f[i-1][j][k]*k%mod)%mod;
}
if(l[i]<=1&&r[i]>=1){
f[i][j+1][k+1] = (f[i][j+1][k+1]+2*f[i-1][j][k])%mod;
f[i][j][k] = (f[i][j][k]+2*f[i-1][j][k]*k%mod)%mod;
}
if(r[i]==2){
f[i][j+1][k+2] = (f[i][j+1][k+2]+f[i-1][j][k])%mod;
f[i][j][k+1] = (f[i][j][k+1]+f[i-1][j][k]*k%mod)%mod;
f[i][j][k+1] = (f[i][j][k+1]+2*f[i-1][j][k]*j%mod)%mod;
if(j) f[i][j-1][k] = (f[i][j-1][k]+2*(j-1)%mod*k%mod*f[i-1][j][k])%mod;
}
}
}
}
cout<<f[n][1][0]<<"\n";
}
return 0;
}
梦与现实间挣扎着,所求为何
你可以借走我的文章,但你借不走我的智慧 虽然我是傻逼本文来自博客园,作者:cztq,转载请注明原文链接:https://www.cnblogs.com/cztq/p/17829433.html