zoukankan      html  css  js  c++  java
  • 省选测试41

    省选测试41

    总结

    (T1,T3) 都是推式子的题,(T2) 是一个套路题,之前没有见过。

    A. 多边形

    分析

    (k>3) 时无解,因为多边形外角和为(360)。一个锐角对应一个(>90)的外角,故最多(3)个。

    对于 (k leq 3) 的情况大力分类讨论即可。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=1e6+5,mod=1000109107;
    inline int addmod(rg int now1,rg int now2){
    	return now1+=now2,now1>=mod?now1-mod:now1;
    }
    inline int delmod(rg int now1,rg int now2){
    	return now1-=now2,now1<0?now1+mod:now1;
    }
    inline int mulmod(rg long long now1,rg int now2){
    	return now1*=now2,now1>=mod?now1%mod:now1;
    }
    int t,n,m,k,jc[maxn],jcc[maxn],ny[maxn];
    void pre(){
    	ny[1]=1;
    	for(rg int i=2;i<maxn;i++) ny[i]=mulmod(mod-mod/i,ny[mod%i]);
    	jc[0]=jcc[0]=1;
    	for(rg int i=1;i<maxn;i++) jc[i]=mulmod(jc[i-1],i),jcc[i]=mulmod(jcc[i-1],ny[i]);
    }
    int getC(rg int nn,rg int mm){
    	if(nn<mm) return 0;
    	return mulmod(jc[nn],mulmod(jcc[mm],jcc[nn-mm]));
    }
    int getsum(rg int now){
    	return mulmod(now,mulmod(now+1,ny[2]));
    }
    int solve3(){
    	if(m!=3) return 0;
    	else return delmod(getC(n,m),mulmod(n,getsum(n/2-1)));
    }
    int solve2(){
    	if(m==3) return mulmod(n,getsum(n/2-1));
    	else return mulmod(n,addmod(mulmod(2,getC(n/2,m-1)),getC(n/2,m-2)));
    }
    int solve1(){
    	rg int ans=addmod(mulmod(getC(n/2,m-2),n/2),getC(n/2,m-1));
    	ans=delmod(mulmod(ans,n),addmod(mulmod(2,solve2()),mulmod(3,solve3())));
    	return ans;
    }
    int solve0(){
    	return delmod(getC(n,m),addmod(solve1(),addmod(solve2(),solve3())));
    }
    int main(){
    	pre();
    	read(t);
    	while(t--){
    		read(n),read(m),read(k);
    		if(k>=4) printf("0
    ");
    		else if(k==3) printf("%d
    ",solve3());
    		else if(k==2) printf("%d
    ",solve2());
    		else if(k==1) printf("%d
    ",solve1());
    		else printf("%d
    ",solve0());
    	}
    	return 0;
    }
    

    B. 仙人掌

    分析

    什么乱七八糟的仙人掌,就是一棵树。

    对于每一个点开一颗 (trie) 树维护子树内的异或和,支持整体加一、删除一个数、加入一个数。

    由低位到高位建 (trie),整体加一的时候相当于把最低位的一个 (0) 变成 (1),把后面所有的 (1) 都翻转成 (0)

    具体实现的时候就是交换左右儿子,递归 (0) 的那一部分子树。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=1e6+5,mod=1000109107;
    inline int addmod(rg int now1,rg int now2){
    	return now1+=now2,now1>=mod?now1-mod:now1;
    }
    inline int delmod(rg int now1,rg int now2){
    	return now1-=now2,now1<0?now1+mod:now1;
    }
    inline int mulmod(rg long long now1,rg int now2){
    	return now1*=now2,now1>=mod?now1%mod:now1;
    }
    int h[maxn],tot=1,n,m,tag[maxn],a[maxn],fa[maxn],ans;
    struct asd{
    	int to,nxt;
    }b[maxn];
    void ad(rg int aa,rg int bb){
    	b[tot].to=bb;
    	b[tot].nxt=h[aa];
    	h[aa]=tot++;
    }
    void dfs(rg int now,rg int lat){
    	fa[now]=lat;
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==lat) continue;
    		dfs(u,now);
    	}
    }
    int rt[maxn],ch[maxn*10][2],sum[maxn*10],num[maxn*10],cnt;
    void push_up(rg int da,rg int bit){
    	num[da]=num[ch[da][0]]+num[ch[da][1]];
    	sum[da]=sum[ch[da][0]]^sum[ch[da][1]];
    	if(num[ch[da][1]]&1) sum[da]^=(1<<(bit-1));
    }
    void insert(rg int &da,rg int val,rg int bit){
    	if(!da) da=++cnt;
    	if(bit>20){
    		num[da]++;
    		return;
    	}
    	if(val&(1<<(bit-1))) insert(ch[da][1],val,bit+1);
    	else insert(ch[da][0],val,bit+1);
    	push_up(da,bit);
    }
    void del(rg int da,rg int val,rg int bit){
    	if(bit>20){
    		num[da]--;
    		return;
    	}
    	if(val&(1<<(bit-1))) del(ch[da][1],val,bit+1);
    	else del(ch[da][0],val,bit+1);
    	push_up(da,bit);
    }
    void xg(rg int da,rg int bit){
    	if(bit>20) return;
    	std::swap(ch[da][0],ch[da][1]);
    	if(ch[da][0]) xg(ch[da][0],bit+1);
    	push_up(da,bit);
    }
    int getans(rg int now){
    	rg int nans=0;
    	if(fa[now]) nans^=(a[fa[now]]+tag[fa[fa[now]]]);
    	nans^=sum[rt[now]];
    	return nans;
    }
    int main(){
    	memset(h,-1,sizeof(h));
    	read(n),read(m);
    	rg int aa,bb;
    	for(rg int i=1;i<n;i++){
    		read(aa),read(bb);
    		ad(aa,bb),ad(bb,aa);
    	}
    	dfs(1,0);
    	for(rg int i=1;i<=n;i++) if(fa[i]) insert(rt[fa[i]],0,1);
    	rg int nans=0;
    	for(rg int i=1;i<=m;i++){
    		read(aa);
    		tag[aa]++;
    		if(fa[aa]){
    			if(fa[fa[aa]]) del(rt[fa[fa[aa]]],a[fa[aa]]+tag[fa[fa[aa]]],1);
    			a[fa[aa]]++;
    			if(fa[fa[aa]]) insert(rt[fa[fa[aa]]],a[fa[aa]]+tag[fa[fa[aa]]],1);
    		}
    		xg(rt[aa],1);
    		nans=getans(aa);
    		ans=addmod(ans,mulmod(nans,addmod(mulmod(i,i),i)));
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    C. 多项式

    分析

    首先把题目中给的公式写出来,这些公式推导的时候会用到。

    (x^{underline{n}}=sum_{k=0}^n(-1)^{n-k}s(n,k)x^k)

    (x^n=sum_{k=0}^nS(n,k)x^{underline{k}})

    (Delta^n f(x) sum_{i=0}^n(-1)^{n-i}inom{n}{i}f(x+i))

    (Delta^n f(x) sum_{i=0}^dc_iinom{x}{n-i},f(x)=sum_{i=0}^dc_iinom{x}{i})

    考虑二项式反演,设 (g[k]) 为钦定前 (n) 个变量中有 (k) 个变量 (>t) 的方案数。

    那么 (g[k]=inom{n}{k}inom{s-kt}{m})

    含义就是从前面的 (n) 个位置中选出 (k) 个不合法的,那么还剩下 (s-kt) 个数分给 (m) 个位置,每一个位置上不能为空,数可以不放完。

    用插板法,新加入一个集合存放多余的元素,再新加一个元素分给这个集合。

    根据二项式反演,

    (ans=sum_{i=0}^n(-1)^iinom{n}{i}inom{s-it}{m})

    (i=n-i),则

    (ans=sum_{i=0}^n(-1)^{n-i}inom{n}{i}inom{s-nt+it}{m})

    (f(x)=inom{s-nt+xt}{m})

    那么根据题目中的第三个式子

    (Delta^n f(x)=sum_{i=0}^n(-1)^{n-i} inom{n}{i}inom{m}{s-nt+xt+it})

    同时根据第四个式子,

    (Delta^n f(0)=sum_{i=0}^mc_iinom{i-n}{0})

    注意到只有 (inom{0}{0}) 才有值,所以 (Delta^n f(0)=c_n)

    所以只要求出 (c_n) 的值即可。

    根据最后一个式子,(f(x)=sum_{i=0}^mc_iinom{x}{i})

    暴力展开 (f(x)=sum_{i=0}^mc_i frac{x^{underline{i}}}{i!})

    仍然使用题目中的良心公式,

    (f(x)=sum_{i=0}^mfrac{c_i}{i!} sum_{j=0}^i(-1)^{i-j}s(i,j)x^j)

    同时根据我们最开始的定义式,

    (f(x)=inom{s-nt+xt}{m}=frac{1}{m!}(s-nt+xt)^{underline{m}}=frac{1}{m!}sum_{i=0}^m(-1)^{m-i}s(m,i)(s-nt+xt)^i)

    对于任意 (x^k) 项,这两个式子的系数都是相同的

    所以

    (sum_{i=k}^mfrac{c_i}{i!}(-1)^{i-k}s(i,k)x^k=frac{1}{m!}sum_{i=k}^m(-1)^{m-i}s(m,i)inom{i}{k}t^k(s-nt)^{i-k}x^k)

    对于这个式子可以依次求出 (c_m)(c_n) 的值,然后回代

    对于两个阶乘,可以把 (frac{1}{m!}) 乘到右边,因为 (m-i) 不会很大,所以可以直接算

    对于组合数,可以预处理出一列,然后去递推

    对于第一类斯特林数,我们会发现 (n-m) 很小,也就是说有很多个环的大小都为 (1),我们可以去枚举有哪些环的大小大于 (1)

    那么就是 (sum_{i=0}^{n-m}inom{n}{m-i}ss(n-m+i,i))

    其中 (ss(n,m)) 表示将 (n) 个元素排成 (m) 个环,环的大小至少为 (2) 的方案数

    递推式为 (ss(n,m)=(n-1)ss(n-1,m)+(n-1)ss(n-2,m-1))

    实现的时候要精细一下。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=2e3+5,mod=1000109107;
    inline int addmod(rg int now1,rg int now2){
    	return now1+=now2,now1>=mod?now1-mod:now1;
    }
    inline int delmod(rg int now1,rg int now2){
    	return now1-=now2,now1<0?now1+mod:now1;
    }
    inline int mulmod(rg long long now1,rg int now2){
    	return now1*=now2,now1>=mod?now1%mod:now1;
    }
    int ksm(rg int ds,rg int zs){
    	rg int nans=1;
    	while(zs){
    		if(zs&1) nans=mulmod(nans,ds);
    		ds=mulmod(ds,ds);
    		zs>>=1;
    	}
    	return nans;
    }
    int n,m,t,ans,c[maxn][maxn],prestr[maxn][maxn],str[maxn][maxn],jc[maxn],jcc[maxn],ny[maxn],beg;
    long long s;
    int getC(rg int nn,rg int mm){
    	if(nn<mm || nn<0 || mm<0) return 0;
    	return c[nn-beg][mm-beg];
    }
    int getpres(rg int nn,rg int mm){
    	rg int nans=0;
    	for(rg int i=0;i<=nn-mm;i++){
    		nans=addmod(nans,mulmod(getC(nn,mm-i),prestr[nn-mm+i][i]));
    	}
    	return nans;
    }
    int getS(rg int nn,rg int mm){
    	return str[nn-n][mm-n];
    }
    void pre(){
    	ny[1]=1;
    	for(rg int i=2;i<maxn;i++) ny[i]=mulmod(mod-mod/i,ny[mod%i]);
    	jc[0]=jcc[0]=1;
    	for(rg int i=1;i<maxn;i++){
    		jc[i]=mulmod(jc[i-1],i);
    		jcc[i]=mulmod(jcc[i-1],ny[i]);
    	}
    	beg=std::max(0,n-1000);
    	c[0][0]=1;
    	for(rg int i=1;i<maxn;i++){
    		c[i][0]=mulmod(c[i-1][0],mulmod(beg+i,ny[i]));
    	}
    	for(rg int i=1;i<maxn;i++){
    		for(rg int j=1;j<=i;j++){
    			c[i][j]=addmod(c[i-1][j],c[i-1][j-1]);
    		}
    	}
    	prestr[0][0]=1;
    	for(rg int i=2;i<maxn;i++){
    		for(rg int j=1;j<=i;j++){
    			prestr[i][j]=addmod(mulmod(i-1,prestr[i-2][j-1]),mulmod(i-1,prestr[i-1][j]));
    		}
    	}
    	str[0][0]=getpres(n,n);
    	for(rg int i=1;i<=m-n;i++){
    		str[i][0]=getpres(n+i,n);
    	}
    	for(rg int i=1;i<=m-n;i++){
    		for(rg int j=1;j<=i;j++){
    			str[i][j]=addmod(str[i-1][j-1],mulmod(i+n-1,str[i-1][j]));
    		}
    	}
    }
    int xs[maxn];
    void solve(){
    	rg int tmp;
    	for(rg int i=m;i>=n;i--){
    		tmp=1;
    		for(rg int j=m;j>=i+1;j--){
    			xs[i-n]=delmod(xs[i-n],mulmod(xs[j-n],mulmod(tmp,mulmod(getS(j,i),ksm(mod-1,j-i)))));
    			tmp=mulmod(tmp,j);
    		}
    		for(rg int j=i;j<=m;j++){
    			xs[i-n]=addmod(xs[i-n],mulmod(ksm(mod-1,m-j),mulmod(getS(m,j),mulmod(getC(j,i),mulmod(ksm(t,i),ksm((s-1LL*n*t)%mod,j-i))))));
    		}
    		tmp=1;
    		for(rg int j=i+1;j<=m;j++) tmp=mulmod(tmp,ksm(j,mod-2));
    		xs[i-n]=mulmod(xs[i-n],tmp);
    	}
    }
    int main(){
    	read(s),read(t),read(n),read(m);
    	pre();
    	solve();
    	printf("%d
    ",xs[0]);
    	return 0;
    }
    
  • 相关阅读:
    HttpServletRequest对象(一)
    HttpServletResponse对象(二)
    HttpServletResponse对象(一)
    Servlet路径跳转问题
    sevlet的url-pattern设置
    java中使用相对路径读取文件的写法总结 ,以及getResourceAsStream() (转)
    创建第一个servlet程序--HelloServlet
    Eclipse创建一个JAVA WEB项目
    Servlet学习(二):ServletConfig获取参数;ServletContext应用:请求转发,参数获取,资源读取;类装载器读取文件
    Centos7默认安装的docker版本说明
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/14578918.html
Copyright © 2011-2022 走看看