10.21

A.Circle

CF297E
场上秉持着正难反更难的精神,根本没考虑容斥。

正着统计合法方案很难,考虑用总方案数减去不合法方案数。
总方案数比较容易求得,为 \(\binom{n}{m}\)
不合法的可以归为两种情况:

  1. 一种是两边都与当前线段相离。
  2. 另一种是一个与当前线段相交,另一个相离。

第一种情况我们可以求出 \(l_i,r_i\) 分别代表这个线段左边和右边与之相离的线段数,那么当前线段答案为 \(l_i\times r_i\)
与当前线段相交的线段为 \(n-l_i-r_i-1\),那么另一种情况就是 \((n-l_i-r_i-1)\times (l_i+r_i)\) ,由于两条线段相交,所以会算两次,最后除以二即可。

思路对了代码写的是真的快。

点击查看代码
#include <bits/stdc++.h>
#define fr first
#define se second
#define U unsigned
#define LL long long
#define pb push_back
#define pii pair<int,int>
#define pLi pair<LL,int>
#define pLL pair<LL,LL>
#define __ __int128
#define ld long double
#define VE vector<LL>
#define db double

using namespace std;

inline int read()
{
	int x = 0,f = 1;char ch = getchar();
	while(!isdigit(ch)) (ch == '-') && (f = -1),ch = getchar();
	while(isdigit(ch)) x = x*10+ch-48,ch = getchar();
	return x*f;
}

const int N = 2e5+5;
int n,l[N],r[N];
struct Line{int l,r;}L[N];
struct BIT
{
	int c[N];
	inline void A(int i,int k){while(i <= n*2) c[i] += k,i += i&-i;}
	inline int Q(int i){int res = 0;while(i) res += c[i],i -= i&-i;return res;}
	inline void clear(){memset(c,0,sizeof(c));}
}t[3];

int main()
{
	n = read();
	for (int i = 1;i <= n;i++)
	{
		L[i] = {read(),read()};
		if (L[i].l > L[i].r) swap(L[i].l,L[i].r);
	}
	sort(L+1,L+n+1,[](Line a,Line b){return a.r < b.r;});
	for (int i = 1;i <= n;i++)
		r[i] = i-1-t[0].Q(L[i].l),l[i] += t[1].Q(L[i].l-1),t[0].A(L[i].l,1),t[1].A(L[i].r,1);
	t[0].clear();
	for (int i = n;i >= 1;i--)
		l[i] += n-i-t[0].Q(L[i].r)+t[0].Q(L[i].l-1),t[0].A(L[i].l,1);
	LL ans = 1LL*n*(n-1)*(n-2)/6,sum = 0;
	for (int i = 1;i <= n;i++)
		ans -= 1LL*l[i]*r[i],sum += 1LL*(l[i]+r[i])*(n-l[i]-r[i]-1);
	ans -= sum/2;
	cout << ans;
	return 0;
}

B.Stone

我不管,这就是困难 \(\text{dp}\) !!!

逆向考虑,由最终状态来求答案。
首先一段不与 \(1\) 相连的石子,它的方案数是固定的。
\(f_i\) 为只考虑一段连续 \(i\) 颗石子的方案数,枚举最后一个填上的石子 \(j\),则 \(f_i=\sum\limits_{j=1}^{i}(i-j+1)\binom{i-1}{j-1}f_{j-1}f_{i-j}\)
然后考虑与 \(1\) 相连的石子数,设 \(pre_{i,j}\) 为跟位置 \(1\) 连续的有 \(i−1\) 颗石子、并且已经失败了 \(j\) 次的方案数,则 \(pre_{i,j}=i\times pre_{i,j-1}+\sum\limits_{k=2}^{i}(i-k+1)\binom{i+j-2}{i-k}f_{i-k}\times pre_{k-1,j}\)
再求后缀的方案数,设 \(suf_{i,j}\) 为从 \(i\)\(n\)\(j\) 颗石子的方案数,则 \(suf_{i,j}=\sum\limits_{k=0}^{j}\binom{j}{k}f_k\times suf_{i+k+1,j-k}\)
最后我们的 \(ans=\sum\limits_{i=1}^{n}\binom{m}{i+p-1}pre_{i,p}\times suf_{i+2,m-p-i+1}\)
复杂度 \(O(n^2p+nm^2)\)

C.Coins

不会啊,但是 \(O(n^2)\) 暴力分好多。

CF1336C

牛魔忘了有时间复杂度 \(O(n^2)\) 的区间 \(dp\)
感觉这种在开头或末尾填东西的好像好多都是区间 \(dp\),我猜的。

\(f_{l,r}\) 表示用 \(s\) 的前 \(r-l+1\) 个字符拼出\(t_{l...r}\)的方案数。
转移的话先枚举区间长度 \(len\) 和左端点 \(l\)

  • \(s_{len}=t_l,f_{l,r}\) 可以从 \(f_{l+1,r}\) 转移。
  • \(s_{len}=t_r,f_{l,r}\) 可以从 \(f_{l,r-1}\) 转移。
    注意如果字符串长度不同要给 \(t\) 补上通配符,初始化:若能 \(s_1\) 能匹配 \(t_i\)\(f_{i,i} = 2\)

CF1336D

自己想了个很精妙的构造方法结果是假的。

如果一个数 \(a_i>0\) ,那么仅一次查询就能知道具体数值,这点很重要。
首先用 \(2-1-3-1\)\(a_1,a_2,a_3\) 都确定出来,首先 \(1\) 通过两次操作可以求出,先给 \(2\) 加一是为了能解出下面的方程来求出 \(2\),求出 \(2\) 的同时 \(3\) 也出来了。
\(\left\{\begin{matrix} bc=k_1\\b(c+1)=k_2\end{matrix}\right.\)
同时我们保证了一个重要的性质——\(a_1,a_2,a_3\) 都非零。
事实上有方法只需要四次就能确定 \(a_{1\dots4}\),但是由于没有仅是确定而没能保证非零,所以后面方程解不出来就寄掉了。
然后我们通过这几次询问可以确定 \(a_4\) 是否为零,而这个一旦确定了,那么我们仅需要一次查询就能知道 \(a_4\) 的具体数值了,同样对 \(4\) 进行询问时我们也能得知 \(5\) 是否为 \(0\),这样一直向后推,最后查询完 \(n-1\) 解方程求出 \(a_n\) 即可。

posted @ 2024-10-21 22:07  ZepX_D  阅读(14)  评论(0)    收藏  举报