我是靠谱客的博主 沉静摩托,最近开发中收集的这篇文章主要介绍agc022F Checkersagc022F Checkers,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

agc022F Checkers

  • n n n个数,第 i i i个数一开始为 ( 1 0 100 ) i (10^{100})^i (10100)i,现在进行 n − 1 n-1 n1次操作,选择两个数 x , y x,y x,y,将它们变为 2 x − y 2x-y 2xy
  • 求最后的剩下的数有多少种结果。 n ≤ 50 nle50 n50

Solution

  • 一开始想的是建成一个二叉树,左儿子乘 − 1 -1 1,右儿子乘 2 2 2,但是我们不知道 2 2 2次幂相同有什么排布规律使得它不算重,所以我们考虑将这个二叉树上的所有 − 1 -1 1的边缩起来。
  • 那么我们会得到一棵树,第 i i i层的数是 + / − 2 i +/-2^i +/2i
  • 接下来考虑关于符号的树形 D P DP DP
  • 从下往上一层一层地加入点,那么当前的点要么是+,要么是-,考虑如果一个点连上奇数个儿子,那么它的权值会乘上-1,考虑一个点连的儿子是有顺序的,那么一个儿子在次序为奇数会再乘上-1。
  • 我们不难发现,对于儿子层的点,假设有 x x x个点要求它的父亲链上对它的影响为+1, y y y个点为-1,那么一个当前层的节点,如果儿子奇数位置为要求+1的点,那么当前点的要求就变成了-1,即我们可以通过儿子来推出父亲的要求。
  • 不妨设 x < = y x<=y x<=y,那么有 y − x y-x yx个新点是奇数个的,剩下的新点的取值可以随便选择,枚举剩下的新点多少个选1,多少个选-1即可。因此我们可以知道,状态只需要记录 ( x − y ) (x-y) (xy)即可。
  • O ( n 4 ) O(n^4) O(n4)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 51
#define ll long long 
#define mo 1000000007
using namespace std;

int n,i,j,k,l;
ll f[maxn][maxn][2],C[maxn][maxn],ans;

int main(){
	freopen("ceshi.in","r",stdin);
	scanf("%d",&n);
	for(C[0][0]=1,i=1;i<=n;i++) for(C[i][0]=1,j=1;j<=i;j++)
		C[i][j]=(C[i-1][j-1]+C[i-1][j])%mo;
	f[0][0][0]=1;
	for(i=0;i<n;i++) for(j=0;j<=i;j++) for(int p=0;p<2;p++) if (f[i][j][p]){
		int x=(p==1)*j,y=(p==0)*j;
		for(k=0;i+j+k<=n;k++) for(l=0;i+j+k+l<=n;l++) if (j+k+l>0) if (i+j+k+l<n||i+j+k+l==n&&j+k+l==1)
		(f[i+j+k+l][max(x+k,y+l)-min(x+k,y+l)][x+k<=y+l]+=f[i][j][p]*C[i+j+k+l][i]%mo*C[j+k+l][y+k])%=mo;
	}
	printf("%lldn",f[n][1][0]);
}

最后

以上就是沉静摩托为你收集整理的agc022F Checkersagc022F Checkers的全部内容,希望文章能够帮你解决agc022F Checkersagc022F Checkers所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(75)

评论列表共有 0 条评论

立即
投稿
返回
顶部