2019 Asia Nanchang D. Interesting Series
链接:https://nanti.jisuanke.com/t/41351
题意:首先题目给了若干定义
定义:Fn=(a^n-1)/(a-1)
定义:s,S为集合
定义:value(s)=F[sum(s)]
定义:sum(s)=s的元素加法和
定义:Ans(k)= sum_{s是S的子集}value(s)[|s|=k]
输入:n a Q,接下来是集合S的n个元素,接下来是Q次询问 每次询问输入Ki
输出:K行 Ans(Ki)%100003 n,q<=1e5
思路:先推样例S={3,1,1},我们把N=3,K=1,2,3都手推一次
对于N=3 :
K=3:S全选C(3,3) Ans(3,3)=a^(s1+s2+s3) ( Ans的第二维表示N)
K=2:S里面3个选2 Ans(2,3)=a^(s1s2)+a^(s2s3)+a^(s1s3)
K=1:S里面3个选1 Ans(1,3)=a^s1+a^s2+a^s3
好像看不出什么
对于N=2:
K=2 Ans(2,2)=a^(s1+s2)=a^s1*a^s2
K=1 Ans(1,2)=a^s1+a^s2
考虑萌新s3带来的影响
Ans(3,3)=Ans(2,2)*a^s3
Ans(2,3)=Ans(1,2)*a^s3+Ans(2,2)
Ans(1,3)=Ans(1,2)+a^s3
感觉是个递推,但n^2 DP显然会T
换一种思路:既然是集合选取元素,那么对于K=0,1,2,3 每个元素选/不选都要考虑在内
假设F(x)为选取的情况,x的指数为选了多少个
对于N=3, F3(x)=1+A(1,3)*x + A(2,3)x^2 + A(3,3)*x^3
对于N=2 F2(x)=1+A(1,2)*x + A(2,2)x^2
F3(x)=1+[A(1,2)+a^s3]x + [A(1,2)*a^s3+A(2,2) ]x^2 + [A(2,2)*a^s3]x^3
考虑s3选/不选的影响 F3(x)=F2(x)*([a^s3]x+1)
猜想Fn(x)=([a^si]*x+1)的积 FFT多个多项式相乘即可
注意:不能用双模数NTT 因为(a^si)先取了100003模 导致 分别用两个大模数算卷积不对
然后我就不知道怎么处理了,只好写FFT
另外:官方题解的F(x)是把指数的意义反过来了,最终算出来是一样的
我们上面算的是F(n)=a^n的贡献,后面-1的贡献显然是C(n,k),分母最后*逆元即可
1081ms
#include<bits/stdc++.h>
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define reu(i,l,u) for(int i=(l);(i)<(int)(u);++(i))
#define all(o) (o).begin(), (o).end()
using namespace std;
typedef long long ll;
typedef double Num; //long double TLE
typedef complex<Num> Cp;
const Num PI = 3.141592653589793238462643383279L;
const int MOD = 100003;
namespace FFT {
void Fuck(int n, Num theta, Cp a[]) {
for(int m = n; m >= 2; m >>= 1) {
int mh = m >> 1;
Cp thetaI = Cp(0, theta);
rep(i, mh) {
Cp w = exp((Num)i*thetaI);
for(int j = i; j < n; j += m) {
int k = j + mh;
Cp x = a[j] - a[k];
a[j] += a[k];
a[k] = w * x;
}
}
theta *= 2;
}
int i = 0;
reu(j, 1, n-1) {
for(int k = n >> 1; k > (i ^= k); k >>= 1) ;
if(j < i) swap(a[i], a[j]);
}
}
void Dft(int n, Cp a[]) { Fuck(n, 2 * PI / n, a); } //不改
void Idft(int n, Cp a[]) { Fuck(n, -2 * PI / n, a); }//不改
void Mul(vector<Cp> &v, vector<Cp> &w) {
int n = 1, vwn = v.size() + w.size() - 1;
while(n < vwn) n <<= 1;
v.resize(n), w.resize(n);
Dft(n, &v[0]);Dft(n, &w[0]);
rep(i, n) v[i] *= w[i];
Idft(n, &v[0]);
rep(i, n) v[i] /= n;
}
}
namespace DLC{
vector<vector<int> > All;//多项式
vector<int> Dfs(int l, int r) {//分治
using namespace FFT;
if(r - l == 1) { //构造多项式
return All[l];
}
int mid = (l + r) / 2;//合并
vector<int> L = Dfs(l, mid), R = Dfs(mid, r);
vector<Cp> Lc(all(L)), Rc(all(R));
Mul(Lc, Rc);
int n = L.size() + R.size() - 1;
vector<int> res(n);
rep(i, n) res[i] = (long long)(Lc[i].real() + .5) % MOD;
return res;
}
}
//非FFT
ll qmod(ll a,ll b){ll res=1;while(b){if(b&1)res=res*a%MOD;a=a*a%MOD;b=b>>1;}return res;}
int fac[100005], inv[100005];
void Init(void) {//预处理阶乘
fac[0] = 1; int lim = 100001;
for(int i = 1; i <= lim; i++) fac[i] = 1ll*fac[i - 1]* i%MOD;
inv[lim] = qmod(fac[lim], MOD - 2);
for(int i = lim - 1; i >= 0; i--) inv[i] = 1ll*inv[i + 1]*(i + 1)%MOD;//乘
}
int C(int x, int y) {return y>x?0:(1ll*fac[x]*inv[y]%MOD*inv[x - y]%MOD);}
int main() {
Init();
using namespace DLC;
int N,aa,Q;scanf("%d%d%d", &N,&aa,&Q);
ll inva=qmod(aa-1,MOD-2);
rep(i, N) {//([a^si]x+1)
vector<int> A;int t;scanf("%d", &t);
A.push_back(1);A.push_back(qmod(aa,t));All.push_back(A);
}
vector<int> ans = Dfs(0, N);
rep(ii, Q) {
int K;
scanf("%d", &K);
printf("%d\n", (ans[K]-C(N,K)+MOD)%MOD*inva%MOD);
}
return 0;
}