省选模拟(61~65)

省选模拟61

1.GTM

\(BIT\)
把所有点按照下标排序后,考虑消灭一个点会给多少个点消灭掉
发现左边速度比它大的和右边速度比它小的都能够通过接触它消灭
继续分情况,考虑左边速度比它小的一些点
如果速度比右边速度的最小值要大的话就可以通过接触右边的点消灭
同理对于右边速度比它大的点只要比左边最大值小就照样可以消灭掉
所以每个点能够消灭的,是速度一段区间内的点\([min,max]\)
然后就是线段覆盖问题了

2.字符串游戏

?
考虑已经知道答案是多少了,然后就是有一个\(ans*n\)的网格
\(t\)串在上
现在要求从每个\(t\)串上的点走到\(s\)串的某个位置\(pos[i]\),并且要求路径不能有交
求最小的\(ans\)
发现首先这个\(pos\)是单调递增的才行
然后就是考虑为什么会有\(ans\)这个长,是因为路径被迫在\(y!=0\)的时候转弯了
也就是后边有多少个\(pos<i\),答案就至少是多少
所以用个单调队列记录下后缀的\(pos\)在队头删掉大于\(i\)\(pos\)然后更新答案就可以了

3.ACE

考虑容斥
用已有的边容斥,容斥的是至少用了几条坏边
用了几条坏边就会少几个连通块,所以可以用连通块来容斥
(可是我想不到)
所以状压\(dp[i][S]\)表示\(S\)这个集合形成一条链的方案 数
然后背包集合的方案数\(O(14*3^14)\)
然后求出来了有\(i\)个链的方案数
然后可以自乘\(n\)次,代表了一共有\(i\)条链的方案数
\(*i!\)就代表我至多有\(i\)条链方案数,并且中间连接的边有可能是坏边,所以是容斥

省选模拟62

1.Fable

第一种考虑方法,考虑一个位置的数向前向后了多少位就可以判断出来最终位置

可以发现前面有多少个比它大的数就会向前多少位

对应的,因为\(k>num\)才会向后走,从该位到第\(k\)个比它大位之间比它小的数决定它向后走多少位

按照权值插入查询区间数个数

2.Fiend

暴力的做法就是高斯消元解行列式

因为行列式的解本身代表的就是每种排列的逆序对(正负)的和

正解的话就考虑可并堆

说什么把区间排序然后扫之类的东西

反正搞了一晚上也是没很懂...

3.Flair

\(MTT\)

其实吧,个人比较擅长做这种题

(不用脑子,全是套路)

暴力显然是计算出来每种数量菜品的方案数,然后背包计算出来每种数量的最小花费

考虑正解的话光是枚举菜品就受不了

题目的一个性质是\(c_ic_j<=1e4\),这给我点启发

显然对于大于某个上界的数来说都是一定能被拼出来的

这样的话,这个上界大概率是\(c_i*c_j\)

设全部纸币的\(gcd=g\),那么能被拼出来的只能是\(g\)的倍数

我们先假设所有\(g\)的倍数都能被拼出来

所以只需要得到一种菜品数量模\(g\)的值就可以得到它的最小花费是\(g-i%g(i!=kg)\)

其实看到这种固定的东西就可以想到用多项式快速解决问题鸭

然后得到答案后还有小于\(c_i*c_j\)的一些位置它们的贡献是少的

因此特殊处理\(10000\)以内的数量菜品的东西,相当于补差价了...

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm> 
#define ll long long
using namespace std;
const int N=5e4+50;
const int mod=1e9+7;
const double PI=acos(-1);

inline int rd(register int x=0,register char ch=getchar(),register int f=0){
	while(ch<'0'||ch>'9') f=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
	return f?-x:x;
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
ll mgml(ll a,ll b,ll ans=1){for(;b;b>>=1,a=a*a%mod) if(b&1) ans=ans*a%mod;return ans;}
struct complex{
	double real,imag;
	complex(){}
	complex(double real,double imag):real(real),imag(imag){}
	friend complex operator + (complex a,complex b){return complex(a.real+b.real,a.imag+b.imag);}
	friend complex operator - (complex a,complex b){return complex(a.real-b.real,a.imag-b.imag);}
	friend complex operator * (complex a,complex b){return complex(a.real*b.real-a.imag*b.imag,a.real*b.imag+a.imag*b.real);}
}w[19][65537],ab[N],cd[N],fab[N];

int n,m,p,g;
int al[N],BIT[N],rev[N],spe[N];
int a[N],b[N];
void FFT(complex *a,int len,int opt){
	for(int i=0;i<len;++i){
		rev[i]=(rev[i>>1]>>1)|((i&1)<<BIT[len]-1);
		if(i<rev[i]) swap(a[i],a[rev[i]]);
	}
	complex x,y;
	for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=i<<1)for(int k=0;k<i;++k) x=a[j+k],y=a[j+k+i]*w[BIT[i]][k],a[j+k]=x+y,a[j+k+i]=x-y;
	if(opt==1) return;
	reverse(a+1,a+len);
	for(int i=0;i<len;++i) a[i].real/=len,a[i].imag/=len;
}
void MTT(int *a,int *b){
	int len=1<<((int)log2(g<<1)+1);
	for(int i=0;i<len;++i) ab[i]=cd[i]=complex(0,0);
	for(int i=0;i<g;++i) ab[i]=complex(a[i]>>15,a[i]&32767);
	for(int i=0;i<g;++i) cd[i]=complex(b[i]>>15,b[i]&32767);
	FFT(ab,len,1); FFT(cd,len,1);
	for(int i=0;i<len;++i) fab[i]=ab[i]; reverse(fab+1,fab+len);
	for(int i=0;i<len;++i) fab[i].imag=-fab[i].imag;
	for(int i=0;i<len;++i) ab[i]=ab[i]*cd[i],fab[i]=fab[i]*cd[i];
	FFT(ab,len,-1); FFT(fab,len,-1);
	for(int i=0;i<g;++i) a[i]=0;
	for(int i=0;i<len;++i){
		double x=ab[i].imag,y=ab[i].real,z=fab[i].real;
		ll ans=((((ll)(z+y+0.5)>>1)%mod+mod)<<30ll)+((ll)(z-y+0.5)>>1)%mod+mod+(((ll)(x+0.5)%mod+mod)<<15ll)%mod; ans%=mod;
		a[i%g]=(a[i%g]+ans)%mod;
	}
	
}
int main(){
	for(int i=0,j=1;j<N;++i,j<<=1) BIT[j]=i;
	for(int i=0;i<=16;++i) for(int j=0;j<1<<i;++j) w[i][j]=complex(cos(PI*j/(1<<i)),sin(PI*j/(1<<i)));
	for(int T=rd();T;--T){
		n=rd();m=rd();p=rd(); g=0;
		memset(al,0,sizeof al); al[0]=1;
		for(int i=1;i<=m;++i){
			int x=rd(); g=gcd(g,x);
			for(int j=x;j<N;++j) al[j]|=al[j-x];
		}
		for(int i=N-2;i;--i) if(al[i]) spe[i]=0; else spe[i]=spe[i+1]+1;
		for(int i=0;i<g;++i) a[i]=b[i]=0; a[0]=100-p; a[1%g]=p; b[0]=1;
		for(int i=n;i;i>>=1,MTT(a,a)) if(i&1) MTT(b,a);
		int ans=0;
		for(int i=1;i<g;++i) ans=(ans+1LL*b[i]*(g-i)%mod)%mod;
		for(int i=1,lim=min(10000,n),C=n;i<=lim;++i){
			int r=spe[i]-(i%g==0?0:g-i%g);
			ans=(ans+1LL*C*r%mod*mgml(p,i)%mod*mgml(100-p,n-i)%mod)%mod;
			C=1LL*C*mgml(i+1,mod-2)%mod*(n-i)%mod;
		}
		printf("%d\n",(ans%mod+mod)%mod);
	}
	return 0;
}

省选模拟63

1.大佬的难题

原题

2.回文串

\(PAM+LCT\)

3.营养餐

阶梯\(NIM\)
必胜条件\(SG(i)(dep[i]&1)\)异或和

省选模拟65

1.容器

\(dp\)
\(n\)点每个点的最大覆盖次数为\(T\),\(K\)次操作,每次覆盖一个非空区间,问合法覆盖方案数
\(f[i][j][k]\)表示考虑到第\(i\)位时,有\(j\)个确定了左端点没确定右端点的区间和\(k\)个两端都没有确定的区间的方案数
转移枚举在\(i\)位置消掉几个1区间,在\(i+1\)位置开始几个2区间.

\[f[i+1][j-d+p][k-p]=mo(f[i+1][j-d+p][k-p]+1LL*f[i][j][k]*C[j][d]%mod*C[k][p]%mod); \]

最后答案是\(f[n+1][0][0]\)

2.果树

线段树
树,每个点有点权,求点权没有相同的链方案数,保证同种点权点不超过20个
考虑相同点权的点对,等价于求链方案数满足如此的点对不会同时出现,同时这样的点对不会超过\(20n\)
考虑祖先关系的\((u,v)\),等价于在\(dfs\)序上\([1,L[son[u]]-1]~[L[v],R[v]]\)以及\([R[son[u]]+1,n]~[L[v],R[v]]\)
否则就是\([L[u],R[u]]~[L[v],R[v]]\)
那么考虑点对关系等价于\(n*n\)的矩阵,就是说上述范围的点对不能计算答案
因此矩阵面积求交然后用全集减掉就是答案

3.流浪

不会呢

posted @ 2020-04-03 18:58  _xuefeng  阅读(144)  评论(0编辑  收藏  举报