题目

题目大意

也懒得解释题目大意了……


正解

正解居然是\(FFT\)?

不要看题目的那个式子这么长,也不要在那个式子上下手。

其实我们会发现,不同的\((x_i-x_j,y_i-y_j,z_i-z_j)\)并不多。

如果我们求出每个三元组的出现次数,后面的就好做了。

那怎么求呢?

祭出我们的大杀器——\(FFT\)。

考虑只有一个维怎么做。设两个多项式分别为\(A\)和\(B\)。

对于\(x_i\),就在\(A\)的\(x_i\)这一位上的系数加一;

对于\(x_j\),就在\(B\)的\(77-x_j\)这一位上的系数加一。

将\(A\)和\(B\)乘起来,那么\(77+x_i-x_j\)就是差\(x_i-x_j\)对应的个数。

对于三维,就将这三个数压成一维的就好了。

实际上也可以用NTT。仔细分析一下,就可以发现每个三元组的出现次数肯定是不超过\(998244353\)的。


正解

  1. using namespace std;
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <cmath>
  7. #define N 1000000
  8. #define MX 3652264
  9. #define mo 998244353
  10. inline int input(){
  11. char ch=getchar();
  12. while (ch<'0' || '9'<ch)
  13. ch=getchar();
  14. int x=0;
  15. do{
  16. x=x*10+ch-'0';
  17. ch=getchar();
  18. }
  19. while ('0'<=ch && ch<='9');
  20. return x;
  21. }
  22. inline int my_pow(int x,int y){
  23. int res=1;
  24. for (;y;y>>=1,x=(long long)x*x%mo)
  25. if (y&1)
  26. res=(long long)res*x%mo;
  27. return res;
  28. }
  29. inline int pow4(int x){x*=x;return x*x;}
  30. #define M (1<<22)
  31. #define bit 22
  32. int n;
  33. struct DOT{
  34. int x,y,z;
  35. inline DOT rev(){return {77-x,77-y,77-z};}
  36. } d[N];
  37. inline int pia(const DOT &a){return (a.x*154+a.y)*154+a.z;}
  38. int a[1<<22],b[1<<22],cnt[1<<22];
  39. int rev[1<<22];
  40. inline void ntt(int *a,int flag){
  41. for (int i=0;i<M;++i)
  42. if (i<rev[i])
  43. swap(a[i],a[rev[i]]);
  44. for (int i=1;i<M;i<<=1){
  45. int wn=my_pow(3,(mo+1)/(i<<1));
  46. if (flag==-1)
  47. wn=my_pow(wn,mo-2);
  48. for (int j=0;j<M;j+=i<<1){
  49. int wnk=1;
  50. for (int k=j;k<j+i;++k,wnk=(long long)wnk*wn%mo){
  51. int x=a[k],y=(long long)wnk*a[k+i]%mo;
  52. a[k]=(x+y>=mo?x+y-mo:x+y);
  53. a[k+i]=(x-y<0?x-y+mo:x-y);
  54. }
  55. }
  56. }
  57. if (flag==-1){
  58. int invm=my_pow(M,mo-2);
  59. for (int i=0;i<M;++i)
  60. a[i]=(long long)a[i]*invm%mo;
  61. }
  62. }
  63. inline void multi(int *a,int *b,int *c){
  64. for (int i=1;i<M;++i)
  65. rev[i]=rev[i>>1]>>1|(i&1)<<bit-1;
  66. ntt(a,1),ntt(b,1);
  67. for (int i=0;i<M;++i)
  68. c[i]=(long long)a[i]*b[i]%mo;
  69. ntt(c,-1);
  70. }
  71. DOT back[M];
  72. int main(){
  73. freopen("geometry.in","r",stdin);
  74. freopen("geometry.out","w",stdout);
  75. int Q;
  76. scanf("%d%d",&n,&Q);
  77. for (int i=1;i<=n;++i)
  78. d[i]={input(),input(),input()};
  79. for (int i=1;i<=n;++i){
  80. a[pia(d[i])]++;
  81. b[pia(d[i].rev())]++;
  82. }
  83. multi(a,b,cnt);
  84. for (int i=0;i<MX;++i){
  85. int j=i;
  86. back[i].z=j%154-77;j/=154;
  87. back[i].y=j%154-77;j/=154;
  88. back[i].x=j-77;
  89. // assert(pia(back[i])==i);
  90. }
  91. while (Q--){
  92. int a=input(),b=input(),c=input(),d=input();
  93. double ans=0;
  94. for (int i=0;i<MX;++i)
  95. if (cnt[i] && (back[i].x|back[i].y|back[i].z))
  96. ans+=(long long)cnt[i]*abs(a*back[i].x+b*back[i].y+c*back[i].z+d)/sqrt(pow4(back[i].x)+pow4(back[i].y)+pow4(back[i].z));
  97. ans/=(long long)n*(n-1);
  98. printf("%.10lf\n",ans);
  99. }
  100. return 0;
  101. }

总结

\(FFT\)和\(NTT\)真是个bug般的存在……

[JZOJ4330] 【清华集训模拟】几何题的更多相关文章

  1. [JZOJ4331] 【清华集训模拟】树

    题目 题目大意 给你一棵带点权的树,求将树变成一堆不相交的链,而且这些链的权值和非负的方案数. 正解 显然这道题是个\(DP\). 首先求个前缀和\(sum\). 为了后面讲述方便,我这样设:\(f_ ...

  2. UOJ_274_[清华集训2016]温暖会指引我们前行_LCT

    UOJ_274_[清华集训2016]温暖会指引我们前行_LCT 任务描述:http://uoj.ac/problem/274 本题中的字典序不同在于空串的字典序最大. 并且题中要求排序后字典序最大. ...

  3. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  4. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

  5. 【UOJ274】【清华集训2016】温暖会指引我们前行 LCT

    [UOJ274][清华集训2016]温暖会指引我们前行 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很 ...

  6. uoj 41 【清华集训2014】矩阵变换 婚姻稳定问题

    [清华集训2014]矩阵变换 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/41 Description 给出 ...

  7. loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主

    #2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较   题目描述 "A fight? Co ...

  8. [LOJ#2329]「清华集训 2017」我的生命已如风中残烛

    [LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ...

  9. [LOJ#2328]「清华集训 2017」避难所

    [LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所 ...

随机推荐

  1. oracle中的round()方法的用法

    [oracle中的round()方法的用法] Round( ) 函数 传回一个数值,该数值是按照指定的小数位元数进行四舍五入运算的结果 oracle一般常用于计算表空间内存还有多少空间 语法 ROUN ...

  2. TRUNCATE - 清空一个表

    SYNOPSIS TRUNCATE [ TABLE ] name DESCRIPTION 描述 TRUNCATE 快速地从一个表中删除所有行.它和无条件的 DELETE 有同样的效果,不过因为它不做表 ...

  3. Linux 进程间通信 共享内存

    1.特点: 1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝.如管道当在内核空间创建以后,用户空间需要内存  拷贝,需要拷贝数据,所以效率低. 2)为了在多个进 ...

  4. Java 二叉树遍历相关操作

    BST二叉搜索树节点定义: /** * BST树的节点类型 * @param <T> */ class BSTNode<T extends Comparable<T>&g ...

  5. CentOS7-安装最新版本GIT(git version 2.18.0)

    Git安装方式有两种一种是yum安装一种是编译安装: 一.yum命令安装,此方法简单,会自动安装依赖的包,而且会从源里安装最新的版本,如果仓库不是最新的话安装的也不是最新Git. sudo yum i ...

  6. JAVA java调用C++动态链接库dll,有详细过程。VS2015+Eclipse以及失败解决方案

    一.新建Java工程,在Java类中声明一个native的方法 新建Java项目 在新建的项目中创建packet(包),并且在包下创建一个Class(类). 接下来,在该类中添加如下代码: ? 1 2 ...

  7. spring5.02版快速入门

    spring5.02版快速入门分为以下 四步, 1. 引入依赖 2. 创建beans.xml配置文件 3 创建相应的接口实现类(仅仅是快速创建,实现类不给任何方法) 4. 创建容器对象,根据id获取对 ...

  8. flutter 插件

    flutter_spinkit loading动画

  9. 引入CSS的方法

    ##1 关于引入css样式的方法: 1 外部引入: <link rel="stylesheet" type="text/css" href="& ...

  10. Golang 交叉编译跨平台的可执行程序 (Mac、Linux、Windows )

    起因: 在项目中,我们每一次提交都需要添加commit 信息,而且我们的commit 信息,比较繁琐.我决定用golang语言编写一个小工具. 我决定使用语言:golang,使用工具:gox包. go ...