也懶得解釋題目大意了……
正解居然是fft
fftff
t?不要看題目的那個式子這麼長,也不要在那個式子上下手。
其實我們會發現,不同的(xi
−xj,
yi−y
j,zi
−zj)
(x_i-x_j,y_i-y_j,z_i-z_j)
(xi−x
j,y
i−y
j,z
i−z
j)並不多。
如果我們求出每個三元組的出現次數,後面的就好做了。
那怎麼求呢?
祭出我們的大殺器——fft
fftff
t。考慮只有乙個維怎麼做。設兩個多項式分別為a
aa和bbb。
對於x
ix_i
xi,就在a
aa的x
ix_i
xi這一位上的係數加一;
對於x
jx_j
xj,就在b
bb的77−x
j77-x_j
77−xj
這一位上的係數加一。
將a
aa和b
bb乘起來,那麼77+x
i−xj
77+x_i-x_j
77+xi
−xj
就是差xi−
xj
x_i-x_j
xi−xj
對應的個數。
對於三維,就將這三個數壓成一維的就好了。
實際上也可以用ntt。仔細分析一下,就可以發現每個三元組的出現次數肯定是不超過998244353
998244353
998244
353的。
using
namespace std;
#include
#include
#include
#include
#include
#define n 1000000
#define mx 3652264
#define mo 998244353
inline
intinput()
while
('0'
<=ch && ch<=
'9')
;return x;
}inline
intmy_pow
(int x,
int y)
inline
intpow4
(int x)
#define m (1<<22)
#define bit 22
int n;
struct dot;}
} d[n]
;inline
intpia
(const dot &a)
int a[
1<<22]
,b[1
<<22]
,cnt[
1<<22]
;int rev[
1<<22]
;inline
void
ntt(
int*a,
int flag)}}
if(flag==-1
)}inline
void
multi
(int
*a,int
*b,int
*c)dot back[m]
;int
main()
;for
(int i=
1;i<=n;
++i)
multi
(a,b,cnt)
;for
(int i=
0;i++i)
while
(q--
)return0;
}
f ft
fftff
t和nt
tntt
ntt真是個bug般的存在……
JZOJ 4330 清華集訓模擬 幾何題
這題的複雜度是o 106log 106 的fft 害怕.jpg 預處理cnt i j k 表示x,y,z的差為i,j,k的有多少對,首先,xi xj可以變成xi mx xj mx為最大xi 那麼每位都是非負數了,現在要做3維的多項式乘法,考慮用2mx進製儲存這三個數,壓在一起變乙個數,這樣就把3維變...
JZOJ4331 清華集訓模擬 樹
給你一棵帶點權的樹,求將樹變成一堆不相交的鏈,而且這些鏈的權值和非負的方案數。顯然這道題是個dpdp dp。首先求個字首和sum sumsu m。為了後面講述方便,我這樣設 fi,jf fi,j 表示以i ii為根的子樹,其中某條鏈從x xx伸出到i ii的方案數,而且sum x jsum x j ...
JZOJ4331 清華集訓模擬 樹
給你一棵帶點權的樹,求將樹變成一堆不相交的鏈,而且這些鏈的權值和非負的方案數。顯然這道題是個 dp 首先求個字首和 sum 為了後面講述方便,我這樣設 f 表示以 i 為根的子樹,其中某條鏈從 x 伸出到 i 的方案數,而且 sum x j 還有設 g i 表示以 i 為根的,沒有伸出去的鏈的方案數...