题目:http://www.gdfzoj.com/oj/contest/472/problems/1
给定n个数1,2,3...n,现在选出2个集合A和B,满足:
1 A和B的交集不得为空
2 A和B不得相互包含(A=B也属于相互包含)
注意: 在这里我们认为: (A,B)和(B,A)是同一种方案
求选出集合A和B的方案数
n<=1e13
来自xbc的方法:
看到这范围一看就是推公式(这点我也想到了。。。但不会推啊啊啊)
对于每个数有4种情况:
1.A 2.B 3.A交B 4.全集U-A并B
题目限制条件可理解为:
1、2、3集合内不能为空
那么利用容斥原理即为:
ans=所有情况 - 至少1个集合空 + 至少2个集合空 - 3个集合全空
很容易推出公式:
ans=4^n - 3*3^n + 3*2^n - 1
n很大要用快速幂
对于除2详见:https://blog.csdn.net/scutbenson/article/details/83750020
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int value=100000007;
long long ksm(int x,long long y)
{
long long a1;
if (y==0)
return 1;
if (y==1)
return x;
a1=ksm(x,y/2);
if (y%2==1)
return (a1*a1*x)%value;
else
return (a1*a1)%value;
}
int main()
{
long long a1,a2,a3,n,ans;
freopen("a.txt","r",stdin);
scanf("%lld",&n);
a1=ksm(4,n);
a2=ksm(3,n+1);
a3=ksm(2,n);
ans=(a1-a2+3*a3-1)%value;
if (ans<0)
ans+=value;
ans*=50000004;
printf("%lld\n",ans%value);
return 0;
}