CodeChef - COUNTREL Count Relations

题目链接
给你一个长为 N N N 1 , 2 , 3 , . . . . N 1,2,3,....N 1,2,3,....N的序列,让你求出两种关系各个有多少可能;
R 1 R_1 R1,由于 x , y x,y x,y互不是子集,且交集为空。我们可以这样考虑:先对 x x x进行分析,假定 x x x中有 X X X个元素,因为空集是所有集合的子集,所以显然 x x x必不能不取且不能取满 N N N个,那么当 x x x X X X个元素时,就有
C ( N X ) ( 1 X n 1 ) C(_N^X)(1\leq X\leq n-1) C(NX)(1Xn1)种取值方案。
那么剩下的 n x n-x nx个数字就要留给 y y y,显然 y y y集合中必然有元素,假定 y y y中有 Y Y Y个元素,所以在当前情况下有
C ( N X Y ) ( 1 Y n X ) C(_{N-X}^Y),(1\leq Y\leq n-X) C(NXY)(1YnX)种取值.
那么综上所述,第一个问题的答案就有 X = 1 N 1 ( C ( N X ) Y = 1 N X C ( N X Y ) ) \sum_{X=1}^{N-1}(C(_N^X)*\sum_{Y=1}^{N-X}C(_{N-X}^Y)) X=1N1(C(NX)Y=1NXC(NXY)).
然后就是大力化简这个式子了。
先考虑 Y = 1 N X C ( N X Y ) \sum_{Y=1}^{N-X}C(_{N-X}^Y) Y=1NXC(NXY),由组合数的基本公式可知 Y = 0 N X C ( N X Y ) = 2 N X \sum_{Y=0}^{N-X}C(_{N-X}^Y)=2^{N-X} Y=0NXC(NXY)=2NX,那么 Y = 1 N X C ( N X Y ) = 2 N x 1 \sum_{Y=1}^{N-X}C(_{N-X}^Y)=2^{N-x}-1 Y=1NXC(NXY)=2Nx1;
那么上式可化简为
X = 1 N 1 C ( N X ) ( 2 N X 1 ) = X = 1 N 1 C ( N X ) 2 N X X = 1 N 1 C ( N X ) \sum_{X=1}^{N-1}C(_N^X)*(2^{N-X}-1) \\=\sum_{X=1}^{N-1}C(_N^X)*2^{N-X}-\sum_{X=1}^{N-1}C(_N^X) X=1N1C(NX)(2NX1)=X=1N1C(NX)2NXX=1N1C(NX)
易知 X = 1 N 1 C ( N X ) = 2 N 2 \sum_{X=1}^{N-1}C(_N^X)=2^N-2 X=1N1C(NX)=2N2
在考虑左半部分,由二项式定理可知 i = 0 N C ( N i ) a i b N i = ( a + b ) N \sum_{i=0}^{N}C(_N^i)a^ib^{N-i}=(a+b)^N i=0NC(Ni)aibNi=(a+b)N
那么左半部分可化简为 ( 1 + 2 ) N C N 0 2 N C N N 2 0 = 3 N 2 N 1 (1+2)^N-C_N^02^N-C_N^N2^0=3^N-2^N-1 (1+2)NCN02NCNN20=3N2N1
即原式可化简为 3 N 2 N 1 2 N + 2 = 3 N 2 N + 1 + 1 3^N-2^N-1-2^N+2=3^N-2^{N+1}+1 3N2N12N+2=3N2N+1+1,由于 x , y x,y x,y无序,所以除二即为第一部分最后答案。
第二部分:要求 x , y x,y x,y有交集,那么我们可以先设交集的长度为 i i i,那么剩下的部分就是 x , y x,y x,y个站一些不空且不相交的部分,那么显然答案就是
i = 1 N 2 j = 1 n i 1 C ( N i j ) k = 1 N i j C ( N i j k ) \sum_{i=1}^{N-2}\sum_{j=1}^{n-i-1}C(_{N-i}^j)\sum_{k=1}^{N-i-j}C(_{N-i-j}^k) i=1N2j=1ni1C(Nij)k=1NijC(Nijk).
化简和上面一样,多用几次二项式定理就行了。
化简出来就是 4 N 3 N + 1 1 + 3 2 N 4^N-3^{N+1}-1+3*2^N 4N3N+11+32N,同样答案除以2即可。

#include<bits/stdc++.h>

#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back

using namespace std;

LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
const int N = 2e5 +11;
const int mod=100000007;
LL Inv[N],Fac[N];
void P(){
	Fac[0]=1;
	for(int i=1;i<N;i++)Fac[i]=Fac[i-1]*i%mod;
	Inv[N-1]=powmod(Fac[N-1],mod-2,mod);
	for(int i=N-2;i>=0;i--)Inv[i]=Inv[i+1]*(i+1)%mod;
}
LL get(int l,int r){
	return Fac[l]*Inv[r]%mod*Inv[l-r]%mod;
}

LL n;
int main(){
	ios::sync_with_stdio(false);
	// P();
	int t;
	for(cin>>t;t;t--){
		cin>>n;
		cout<<(powmod(3,n,mod)-powmod(2,n+1,mod)%mod+1+2*mod)%mod*powmod(2,mod-2,mod)%mod<<' ';
		cout<<(powmod(4,n,mod)-powmod(3,n+1,mod)-1+3*powmod(2,n,mod)%mod+2*mod)%mod*powmod(2,mod-2,mod)%mod<<endl;
	}
	return 0;
}

全部评论

相关推荐

01-28 16:12
中南大学 Java
几年前还没有chatgpt的时候,刷题真的是很痛苦。刷不出来只能看题解,题解有几个问题:第一个是每次看的写题解的人都不一样,很难有一个统一的思路;第二个也是最重要的是,题解只提供了作者自己的思路,但是没有办法告诉你你的思路哪里错了。其实很少有错误的思路,我只是需要被引导到正确的思路上面去。所以传统题解学习起来非常困难,每次做不出来难受,找题解更难受。但是现在chatgpt能做很多!它可以这样帮助你&nbsp;-1.&nbsp;可以直接按照你喜欢的语言生成各种解法的题解和分析复杂度。2.&nbsp;把题和你写的代码都发给它,它可以告诉你&nbsp;你的思路到底哪里有问题。有时候我发现我和题解非常接近,只是有一点点🤏想错了。只要改这一点点就是最优解。信心倍增。3.&nbsp;如果遇到不懂的题解可以一行一行询问为什么要这样写,chatgpt不会嫌你烦。有时候我觉得自己的range写错了,其实那样写也没错,只是chat老师的题解有一点优化,这个它都会讲清楚。4.&nbsp;它可以帮你找可以用同类型解法来做的题。然后它可以保持解法思路不变,用一个思路爽刷一个类型的题。如果题目之间思路又有变化,它会告诉你只有哪里变了,其他的地方还是老思路。5.&nbsp;它也可以直接帮你总结模板,易错点。经过chat老师的指导,我最大的改变是敢刷题了。之前刷题需要先找某一个人写的算法题repo,然后跟着某一个人他的思路刷他给的几个题。如果想写别的题,套用思路失败了,没有他的题解,也不知道到底哪里错了;看别人的题解,思路又乱了。这个问题在二分查找和dp类型的题里面特别常见。但是现在有chat老师,他会针对我的代码告诉我我哪里想错了,应该怎么做;还按照我写代码的习惯帮我总结了一套属于我的刷题模板。每天写题全是正反馈!
明天不下雨了:那我建议可以用 chatgpt atlas 或者 dia 去刷,也可以用 chrome 加个 ai 插件去刷 左边刷题右边 chat 效果很好
AI时代的工作 VS 传...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务