[AtCoder Grand Contest 036]F - Square Constraints

题意

好题。明确要用容斥原理。
设i能选择的pi范围为li~ ri。
若能求到对于每个k(0<=k<=n,因为n~ 2n-1的l为0),满足所有pi<=ri,至少有k个pi<li的排列数,就可以用二项式反演进行容斥了。
而没有性质的话这题就不可做了,所以一开始肯定是找性质。而这题最关键的性质就是0~n-1的r肯定都大于l。
把0~ n-1的li-1和n~ 2n-1的r放进一个数组内,然后排序,对于0~ n-1要么选l-1要么选r,而如果我们知道这个区间(0~ p)在整个的顺序(按右端点排序),就可以计算它的贡献了。一开始枚举k,知道了0~ n-1有k个选择了l-1,然后dp[i][j]表示我们已经决策了这个数组内前i个位置,有j个位置选择了l-1的方案数,就可以知道当前决策到的位置所处的顺序。
这题就没了吧。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inline void pr1(int x){write(x),putchar(' ');}
inline void pr2(int x){write(x),puts("");}
struct node
{
	int p,id;
}a[510];
bool cmp(node a,node b)
{
	if(a.p==b.p)return a.id>b.id;
	else return a.p<b.p;
}
int l[510],r[510],f[510][300];
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    int n=read(),m=read();
    for(int i=0;i<2*n;i++)
    {
    	a[i].id=i;r[i]=min(2*n-1,(int)floor(sqrt(4*n*n-i*i)));
    	if(i>=n)l[i]=0,a[i].p=r[i];
    	else {l[i]=ceil(sqrt(n*n-i*i));a[i].p=l[i]-1;}
	}sort(a,a+2*n,cmp);
	int ans=0;
	for(int k=0;k<=n;k++)
	{
		int cnt=0;
		memset(f,0,sizeof(f));f[0][0]=1;
		for(int i=1;i<=2*n;i++)
		{
			if(a[i-1].id<n)cnt++;
			for(int j=0;j<=min(k,cnt);j++)
			{
				if(a[i-1].id<n)
				{
					f[i][j]=1LL*f[i-1][j]*(r[a[i-1].id]+1-(2*n-1-a[i-1].id+k-j))%m;
					if(j>0)(f[i][j]+=1LL*f[i-1][j-1]*(a[i-1].p+1-(i-1-(cnt-j)))%m)%=m;
				}
				else f[i][j]=1LL*f[i-1][j]*(a[i-1].p+1-(i-1-(cnt-j)))%m;
			}
		}
		if(k&1)(ans-=f[2*n][k]-m)%=m;
		else (ans+=f[2*n][k])%=m;
	}pr2(ans);
   	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AtCoder Practice Contest #B - インタラクティブ練習 (Interactive Sorting) 是一道比较有趣的题目。它是一道交互式的排序题目,需要你与一个神秘程序进行交互,以便将一串无序的数字序列排序。 具体来说,这个神秘程序会给你一个长度为 $N$ 的数字序列,然后你需要通过询问它两个数字的大小关系,来逐步确定这个序列的排序顺序。每次询问之后,神秘程序都会告诉你两个数字的大小关系,比如第一个数字比第二个数字小,或者第二个数字比第一个数字小。你需要根据这个信息,来调整这个数字序列的顺序,然后再向神秘程序询问下一对数字的大小关系,以此类推,直到这个数字序列被完全排序为止。 在这个过程中,你需要注意以下几点: 1. 你最多只能向神秘程序询问 $Q$ 次。如果超过了这个次数,那么你的程序会被判定为错误。 2. 在每次询问之后,你需要及时更新数字序列的顺序。具体来说,如果神秘程序告诉你第 $i$ 个数字比第 $j$ 个数字小,那么你需要将这两个数字交换位置,以确保数字序列的顺序是正确的。如果你没有及时更新数字序列的顺序,那么你的程序也会被判定为错误。 3. 在询问的过程中,你需要注意避免重复询问。具体来说,如果你已经询问过第 $i$ 个数字和第 $j$ 个数字的大小关系了,那么你就不需要再次询问第 $j$ 个数字和第 $i$ 个数字的大小关系,因为它们的大小关系已经被确定了。 4. 在排序完成之后,你需要将排序结果按照从小到大的顺序输出。如果你输出的结果不正确,那么你的程序也会被判定为错误。 总的来说,这道题目需要你熟练掌握交互式程序设计的技巧,以及排序算法的实现方法。如果你能够熟练掌握这些技巧,那么就可以顺利地完成这道非传统题了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值