(每日一题)2016 北京ICPC网络赛G hihocoder 1388 (中国剩余定理 + NTT)
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(每日一题)2016 北京ICPC网络赛G hihocoder 1388 (中国剩余定理 + NTT)相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
Weblink
https://vjudge.net/problem/HihoCoder-1388
Problem
给定数组 A A A 和数组 B B B,求:
m i n { ∑ i = 0 n − 1 ( A i − B ( i + k ) m o d n ) 2 ∣ k = 0 , 1 … n − 1 } min \\left\\{ \\sum_{i=0}^{n-1}(A_i-B_{(i+k) \\space mod \\space n})^2\\ \\big | \\ k=0,1\\dots n-1 \\right\\} min{i=0∑n−1(Ai−B(i+k) mod n)2 ∣∣ k=0,1…n−1}
Solution
将式子展开:
m i n { ∑ i = 0 n − 1 ( A i − B ( i + k ) m o d n ) 2 ∣ k = 0 , 1 … n − 1 } = ∑ i = 0 n − 1 A i 2 + ( B ( i + k ) m o d n ) 2 + 2 × A i × B ( i + k ) m o d n = ∑ i = 0 n − 1 A i 2 + ∑ i = 0 n − 1 B i 2 + ∑ i = 0 n − 1 2 × A i × B ( i + k ) m o d n \\begin{aligned} & min \\left\\{ \\sum_{i=0}^{n-1}(A_i-B_{(i+k) \\mod n})^2\\ \\big | \\ k=0,1\\dots n-1 \\right\\}& \\\\ &= \\sum_{i=0}^{n-1}A_i^2+(B_{(i+k) \\mod n})^2+2\\times A_i\\times B_{(i+k) \\mod n}& \\\\ &= \\sum_{i=0}^{n-1}A_i^2+ \\sum_{i=0}^{n-1}B_i^2+ \\sum_{i=0}^{n-1}2\\times A_i\\times B_{(i+k) \\mod n} \\end{aligned} min{i=0∑n−1(Ai−B(i+k)modn)2 ∣∣ k=0,1…n−1}=i=0∑n−1Ai2+(B(i+k)modn)2+2×Ai×B(i+k)modn=i=0∑n−1Ai2+i=0∑n−1Bi2+i=0∑n−12×Ai×B(i+k)modn
显然前面两个都是定值,我们只需要求 2 × ∑ i = 0 n − 1 A i × B ( i + k ) m o d n \\displaystyle2\\times \\sum_{i=0}^{n-1} A_i\\times B_{(i+k) \\mod n} 2×i=0∑n−1Ai×B(i+k)modn 的最小值即可。
经典将 B 数组翻转,然后倍长,这样就是卷积的形式了,我们就可以直接卷了。
然后因为数据较大,FFT 精度不够,并且题目中还没有给模数,可以找两个大模数直接NTT,然后 CRT 合并即可。
模数我选的
1
0
9
10^9
109 ,中间记得用龟速乘,不然会爆 long long
。
Code
(原题的OJ炸了,反正样例过了就是过了(doge))
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000007, G = 3;
const ll mod1 = 1004535809, mod2 = 998244353;
ll M;
int n, m;
ll a[N], b[N];
ll f1[N], f2[N], g1[N], g2[N];
int limit, L;
int RR[N];
ll mul(ll a, ll b, ll mod)
{
ll res = 0;
while(b) {
if(b & 1) res = res + a % mod;
a = a + a % mod;
b >>= 1;
}
return res;
}
ll qpow(ll a, ll b, ll mod)
{
ll res = 1;
while(b) {
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
ll inv(ll x, ll mod)
{
return qpow(x, mod - 2, mod);
}
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if(b == 0) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll z = x;
x = y;
y = z - y * (a / b);
return d;
}
ll mm[5], aa[5];
ll CRT(int n, ll *a, ll *mo)
{
M = mo[1] * mo[0];
ll res = 0;
for(ll i = 0; i < n; ++ i) {
ll Mi = M / mo[i];
ll ti, y;
ll d = exgcd(Mi, mo[i], ti, y);
ti = (ti % mo[i] + mo[i]) % mo[i];
res = (res + mul(mul(a[i], ti, M), Mi, M)) % M;
}
return (res % M + M) % M;
}
void NTT(ll *A, int type, ll mod)
{
for(int i = 0; i < limit; ++ i)
if(i < RR[i])
swap(A[i], A[RR[i]]);
for(int mid = 1; mid < limit; mid <<= 1) {
ll wn = qpow(G, (mod - 1) / (mid * 2), mod);
if(type == -1)
wn = qpow(wn, mod - 2, mod);
for(int len = mid << 1, pos = 0; pos < limit; pos += len) {
ll w = 1;
for(int k = 0; k < mid; ++ k, w = (w * wn) % mod) {
ll x = A[pos + k], y = w * A[pos + mid + k] % mod;
A[pos + k] = (x + y) % mod;
A[pos + k + mid] = (x - y + mod) % mod;
}
}
}
if(type == -1) {
ll limit_inv = inv(limit, mod);
for(int i = 0; i < limit; ++ i)
A[i] = (A[i] * limit_inv) % mod;
}
}
void solve()
{
scanfACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛 The Book List
hihoCoder 1389 Sewage Treatment 二分+网络流+优化 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)
hihoCoder 1392 War Chess 模拟 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)
hihoCoder 1391 Countries 预处理+排序+堆 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)