@description@

给定一个整数 N,统计有多少个 0~2N-1 的排列 \(P_0, P_1, ..., P_{2N-1}\) 满足:

\[N^2 \le i^2 + P_i^2 \le (2N)^2 (0 \le i < 2N)
\]

求合法排列数量 mod m。

Constraints

1≤N≤250, 2≤M≤10^9

Input

输入格式如下:

N M

Output

输出合法排列数量 mod m。

Sample Input 1

2 998244353

Sample Output 1

4

@solution@

根据条件 \(N^2 \le i^2 + P_i^2 \le (2N)^2\),我们可以求得 \(P_i\) 的上下界 \(lb_i \le P_i \le rb_i\)。

当 \(0 \le i < N\) 时,\(lb_i = \sqrt{N^2 - i^2}, rb_i = \sqrt{(2N)^2 - i^2}\)。

当 \(N \le i < 2N\) 时,\(lb_i = 0, rb_i = \sqrt{(2N)^2 - i^2}\)。

注意到当 \(i \ge N\) 时 \(lb_i\) 就始终等于 0 了。这意味着有一半元素有着相同下界。

假如 \(lb_i\) 全都为 0,是否有快捷的计算方法呢?

假如 \(lb_i\) 全都为 0,将 \(rb_i\) 从小到大排好序得到 \(rb'_i\),然后从小到大依次考虑每一个 \(rb'_i\) 的贡献。

因为较大的 \(rb'_i\) 一定包含较小的 \(rb'_j\),这意味着无论 j 选择什么,i 总是会少一个可选择的数。

\(rb'_i\) 对应可以选择 \(rb'_i + 1\) 种数(注意可以选 0),删去前面的已经被占用的就只剩\(rb'_i + 1 - i\) 种数(注意下标从 0 开始)。

那么总贡献为 \(\prod_{i=0}^{2N-1}(rb'_i + 1 - i)\)。

对于有下界的情况,考虑经典容斥一波。

枚举哪些数强制 < lb,那么那些数的限制对应变成 \(P_i < lb_i\),即 \(P_i \le lb_i - 1\)。然后就又可以使用我们上面的方法进行计数。

但是这个是指数级的算法。考虑根据题目性质进行优化。

首先只有 0 ~ N-1 这些数可能会 < lb,那么我们只容斥 0 ~ N-1 的部分。

然后,如果你打个表(或者直接观察),你会发现随着 i 增大,\(lb_i\) 与 \(rb_i\) 是递减的。

而我们计数的时候需要排序后的结果,所以这个性质的价值很大。

最后一点,对于 0 ~ N-1 这些数,有 \(\max\{lb\} <= \min\{rb\}\)。

有了这些结论,我们就可以设计我们的算法了。假设我想要求 k 个 < lb 的方案数 f(k):

N ~ 2N-1 这些数只能取 rb 为上界。排完序后那些比它们上界小的,要么是 N ~ 2N-1 中由于单调性而较小的,要么是 0 ~ N-1 中取 lb-1 为上界时比较小的。

0 ~ N-1 这些数,当取 lb-1 为上界时大致同上,要么是 0 ~ N-1 中由于单调性而较小的,要么是 N ~ 2N-1 较小的。

而取 rb 为上界时,首先有 N ~ 2N-1 由于单调性所以所有都比它小,其次那 k 个取 lb-1 为上界的一定比它小(由上面的性质),最后有 0 ~ N 中那些由于单调性而比它小的。

由此,我们将 0 ~ N-1 以 lb-1 为第一关键字,rb 为第二关键字; N ~ 2N-1 以 rb 为第一关键字,0 为第二关键字,全部进行排序。

从小到大作 dp,令 dp(i, j) 表示前 i 个选出 j 个 < lb 的方案数。最后 f(k) = dp(2N, k)。

总方案为 f(0) - f(1) + f(2) - f(3) + ...

时间复杂度 O(n^3)。

@accepted code@

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define mp make_pair
#define fi first
#define se second
typedef pair<int, int> pii;
const int MAXN = 500;
int N, M;
int add(int x, int y) {return (x + y) % M;}
int mul(int x, int y) {return 1LL*x*y % M;}
int sub(int x, int y) {return add(x, M-y);}
int f[MAXN + 5][MAXN + 5]; pii a[MAXN + 5];
int solve(int t) {
int cnt1 = 0, cnt2 = 0;
f[0][0] = 1;
for(int i=0;i<2*N;i++) {
if( a[i].se == 0 ) {
for(int j=0;j<=cnt2;j++)
f[i+1][j] = mul(f[i][j], a[i].fi - (cnt1 + j) + 1);
cnt1++;
}
else {
f[i+1][0] = 0;
for(int j=0;j<=cnt2;j++)
f[i+1][j+1] = mul(f[i][j], a[i].fi - (cnt1 + j) + 1);
for(int j=0;j<=cnt2;j++)
f[i+1][j] = add(f[i+1][j], mul(f[i][j], a[i].se - (N + cnt2 - j + t) + 1));
cnt2++;
}
}
return f[2*N][t];
}
int main() {
scanf("%d%d", &N, &M);
for(int i=0;i<N;i++) {
a[i].fi = 0, a[i].se = 2*N - 1;
while( a[i].fi*a[i].fi + i*i < N*N ) a[i].fi++; a[i].fi--;
while( a[i].se*a[i].se + i*i > 4*N*N ) a[i].se--;
}
for(int i=N;i<2*N;i++) {
a[i].fi = 2*N - 1, a[i].se = 0;
while( a[i].fi*a[i].fi + i*i > 4*N*N ) a[i].fi--;
}
sort(a, a + 2*N);
int ans = 0;
for(int i=N;i>=0;i--)
ans = sub(solve(i), ans);
printf("%d\n", ans);
}

@details@

抱歉,我不会组合计数.jpg。

@atcoder - AGC036F@ Square Constraints的更多相关文章

  1. [Atcoder AGC029C]Lexicographic constraints

    题目大意:给定$n$个字符串的长度$a_i$,问至少用几种字符可以构造出字符串$s_1\sim s_n$,满足$|s_i|=a_i$且$s_1<s_2<\cdots<s_n$. $ ...

  2. AtCoder刷题记录

    构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...

  3. hs-black 杂题选讲

    [POI2011]OKR-Periodicity 考虑递归地构造,设 \(\text{solve(s)}\) 表示字典序最小的,\(\text{border}\) 集合和 \(S\) 的 \(\tex ...

  4. AtCoder Grand Contest 036

    Preface 这篇已经鸽了好久的说,AGC037都打完了才回来补所以题目可能都记不大清楚了,如有错误请指正 这场感觉难度远高于上一场,从D开始就不会了,E没写(看了题解都不会写),F就是抄曲明姐姐的 ...

  5. AtCoder Grand Contest 036 简要题解

    从这里开始 比赛目录 Problem A Triangle 考虑把三角形移到和坐标轴相交,即 然后能够用坐标比较简单地计算面积,简单构造一下就行了. Code #include <bits/st ...

  6. ZROI 暑期高端峰会 A班 Day1 组合计数

    AGC036F Square Constriants 一定有 \(l_i<p_i\le r_i\). 考虑朴素容斥,枚举每个数是 \(\le l_i\) 还是 \(\le r_i\).对于 \( ...

  7. AtCoder Beginner Contest 069【A,水,B,水,C,数学,D,暴力】

    A - K-City Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement In K-city, ...

  8. AtCoder Beginner Contest 088 (ABC)

    A - Infinite Coins 题目链接:https://abc088.contest.atcoder.jp/tasks/abc088_a Time limit : 2sec / Memory ...

  9. AtCoder Beginner Contest 087 (ABC)

    A - Buying Sweets 题目链接:https://abc087.contest.atcoder.jp/tasks/abc087_a Time limit : 2sec / Memory l ...

随机推荐

  1. 作业-[luogu4396][AHOI2013]-莫队

    <题面> 卡常终究比不上算法的优化…… 这是莫队的有点小坑的题, 首先不一定能想到,想到不一定打对,打对不一定打好. 首先你会发现,这个题的时限是很长的- $n$和$m$也是很大的. 于是 ...

  2. day36 09-Hibernate中的事务:事务处理

    什么是丢失更新呢?有一条数据你查出来了,查出来之后有一个事务A和一个事务B也都过来操作同一个记录.A拿到这条记录之后可能改它的某一个值了,B拿到这条记录之后改它的另外一个值.这个时候A事务提交已经提交 ...

  3. Spring 的初次见面

    简介: Spring Framework 是一个开源的企业级应用程序框架,为构建满足企业级需求的应用程序提供了大量的工具集.推出该框架的原因是在时候用J2EE进行开发是会提高复杂性. Spring三大 ...

  4. vue-li+webpack+iview构建项目步骤

    首先安装各类插件 npm install vue-cli -g vue init webpack demo npm install iview --save npm install less styl ...

  5. 【CS Round #44 (Div. 2 only) A】Frequent Numbers

    [链接]h在这里写链接 [题意] 在这里写题意 [题解] 大水题 [错的次数] 0 [反思] 在这了写反思 [代码] /* */ #include <cstdio> #include &l ...

  6. 解决安装编译工具gcc后无法连接mysql

    在安装编译工具gcc后: yum -y install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml2 ...

  7. PHP的注释规范

    <?php //注释规范 /** *函数的功能 *@param 参数类型 参数名1 参数解析 *@param 参数类型 参数名2 参数解析 *@return 返回值类型 返回值解析 *@auth ...

  8. 【笔记】LR录制方式和常用函数

    本文为本人复习LR时,笔记整理.以备后续查阅. 注意:录制脚本时,选择不同的协议下录制时设置选项也是不相同的,我们这里介绍的是基于协议web(http/html)录制选项设置. 对于web(http/ ...

  9. [case49]聊聊flink的checkpoint配置

    序 本文主要研究下flink的checkpoint配置 实例 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecut ...

  10. 获得CSM(Certified Scrum Master)-价值驱动交付。

    2019年越来越多的企业开始实行敏捷转型,紧随时代潮流,学习最先进的科学管理方法,找到正确的人(团队),为企业交付高价值的产品服务. 导师Ethan ,培训的课程让人收益匪浅,活到老学到老,丰富的知识 ...