PAROVI(ZJNU 1830)
题目大意
对于\(1\)到\(n\)的数字,我们称二元组\((x,y)\)为质数对当且仅当\((x,y)=1\)。现在你要取若干组质数对使得\(\forall i\in[2,n]\),都不满足\(x,y<i\)和\(x,y>=i\),问有多少种质数对的取法。\((n<=20)\)
思路
由于直接做有点抽象,于是我们考虑容斥。首先我们可以\(O(n^4)\)求出所有区间的质数对的个数,然后用状压枚举出满足条件的\(i\),对于这样的几个\(i\),我们能算出使它们满足条件的方案数,最后再利用一下容斥的性质,就能轻松\(AC\)惹~
代码
#include<bits/stdc++.h>
using namespace std;
long long mod=1e9;
int sum[25][25];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
long long poww(long long a,long long n)
{
long long ans=1;
while(n)
{
if(n&1)ans=ans*a%mod;
a=a*a%mod;n>>=1;
}
return ans;
}
int main()
{
int n;
scanf("%d",&n);
if(n==1)
{
printf("0\n");
return 0;
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
for(int k=i;k<=j;k++)
for(int l=k+1;l<=j;l++)
if(gcd(k,l)==1)sum[i][j]++;
long long ans=0;
vector<int>v;
for(int i=0;i<(1<<(n-1));i++)
{
v.clear();
int cnt=0;
int anss=0;
v.push_back(1);
for(int j=0;j<n-1;j++)
{
if((1<<j)&i)
{
v.push_back(j+2);
cnt++;
}
}
for(int j=1;j<(int)v.size();j++)
anss+=sum[v[j-1]][v[j]-1];
anss+=sum[v[cnt]][n];
if(cnt&1)ans=(ans-poww(2,anss)+1+mod)%mod;
else ans=(ans+poww(2,anss)-1+mod)%mod;
}
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号