题目描述
输入格式
第一行包含一个正整数T,表示有T组数据求解
每组数据包含两行,第一行包含两个正整数N,C(c>=2),分别表示空间的
维数和需要选择的暂停点个数
第二行包含N个正整数,依次表示M1,M2....Mn
输出格式
有T行,每行一个非负整数,依次对应每组数据的答案。
-
题解:
- 一个$n$维向量$(p_{1},p_{2}, cdots ,p_{n})$上的整点个数为:$gcd(p_{1},p_{2}, cdots , p_{n})+1$
- 可以枚举这个n维向量,考虑到向量在空间里面自由移动也是不同的方案:
- $ans = sum^{m_{1}}_{p_{1}} sum^{m_{2}}_{p_{2}} cdots sum^{m_{n}}_{p_{n}}(m_{1}-p_{1})(m_{2}-p_{2}) cdots (m_{n}-p_{n}) C_{gcd(p1,p2, cdots ,p_{n}) - 1}^{c - 2} $
- 枚举因子,反演得:
- $ sum_{d} C_{d-1}^{c-2} sum_{g} mu(g) sum_{p_{1}}^{ lfloor frac{m_{1}}{gd} floor} sum_{p_{2}}^{ lfloor frac{m_{2}}{gd} floor} cdots sum_{p_{n}}^{ lfloor frac{m_{n}}{gd} floor} (m_{1}-p_{1}gd) (m_{2}-p_{2}gd) cdots (m_{n}-p_{n}gd) $
- $ = sum_{d} sum_{g|d} C_{d-1}^{c-2} mu(frac{d}{g}) sum_{p_{1}}^{lfloor frac{m_{1}}{d} floor} sum_{p_{2}}^{lfloor frac{m_{2}}{d} floor} cdots sum_{p_{n}}^{lfloor frac{m_{n}}{d} floor} (m_{1}-p_{1}d)(m_{2}-p_{2}d) cdots (m_{n}-p_{n}d)$
- 等差数列求和:
- $ = sum_{d} sum_{g|d} C_{d-1}^{c-2} mu(frac{d}{g}) ( Pi_{i=1}^{n} 2^{-1} lfloor frac{m_{i}}{d} floor (2m_{i} - (lfloor frac{m_{i}}{d} floor + 1 ) d ) )$
- 其中2^{-1}表示2的逆元;
- 到这里是基本的化简;
- 考虑下底分块,由于$Pi$的部分含有d,所以需要把考虑成一个关于$d$的多项式$f$进一步化简:
- $ = sum_{d} sum_{g|d} C_{d-1}^{c-2} mu(frac{d}{g}) (Pi_{i=1}^{n} 2^{-1} lfloor frac{m_{i}}{d} floor ) sum_{j=0}^{n}f_{j}d^{j}$
- $ = sum_{d} ( Pi_{i=1}^{n} 2^{-1} lfloor frac{m_{i}}{d} floor ) sum_{j=0}^{n} f_{j} d^{j} sum_{g|d} C_{d-1}^{c-2} mu(frac{d}{g}) $
- 注意到分块后$lfloor frac{m_{i}}{d} floor $是一个常数,所以$f_{j}$及其以前的部分全都是常数的,后面的部分只和$d$有关,预处理前缀和即可;
- 复杂度:$O(n^{3}sqrt{m} + cnm + cmlogm )$
-
1 #include<bits/stdc++.h> 2 #define il inline 3 #define mod 10007 4 #define iv2 5004 5 using namespace std; 6 const int N=15,M=100010,C=21; 7 int T,n,c,m[N],g[C][N][M],a1[N],a2[N],f[N],fac[M],inv[M],u[M],vis[M],pr[M],pt; 8 il int min(int x,int y){if(x<y)return x;else return y;} 9 il int get(int x,int y){ 10 if(x<mod&&y<mod)return x<y?0:fac[x]*inv[y]%mod*inv[x-y]%mod; 11 else return get(x/mod,y/mod)*get(x%mod,y%mod)%mod; 12 } 13 il int pw(int x,int y){ 14 int re=1;x%=mod; 15 for(;y;y>>=1,x=x*x%mod){ 16 if(y&1)re=x*re%mod; 17 }return re; 18 } 19 void pre(){ 20 for(int i=fac[0]=inv[0]=1;i<=1e5;++i){ 21 fac[i]=fac[i-1]*i%mod; 22 inv[i]=pw(fac[i],mod-2); 23 } 24 u[1]=1; 25 for(int i=2;i<=1e5;++i){ 26 if(!vis[i])u[pr[++pt]=i]=-1; 27 for(int j=1;j<=pt&&pr[j]*i<=1e5;++j){ 28 vis[i*pr[j]]=1; 29 if(i%pr[j]==0){u[i*pr[j]]=0;break;} 30 else u[i*pr[j]]=-u[i]; 31 } 32 } 33 for(int c=2;c<=20;++c) 34 for(int i=1;i<=1e5;++i)if(u[i]) 35 for(int j=1;i*j<=1e5;++j){ 36 g[c][0][i*j]=(g[c][0][i*j]+u[i]*get(j-1,c-2))%mod; 37 } 38 for(int c=2;c<=20;++c) 39 for(int i=1;i<=11;++i) 40 for(int j=1;j<=1e5;++j){ 41 g[c][i][j]=g[c][i-1][j]*j%mod; 42 } 43 for(int c=2;c<=20;++c) 44 for(int i=0;i<=11;++i) 45 for(int j=1;j<=1e5;++j){ 46 g[c][i][j]=(g[c][i][j]+g[c][i][j-1])%mod; 47 } 48 } 49 void cal(int d){ 50 for(int i=0;i<=n;++i)a1[i]=a2[i]=0; 51 a1[0]=1; 52 for(int i=1;i<=n;++i){ 53 int x=(m[i]/d+1)%mod,y=2*m[i]%mod; 54 for(int j=0;j<=i;++j){ 55 a2[j+1]=-a1[j]*x%mod; 56 a1[j]=(a1[j]*y%mod+a2[j])%mod; 57 } 58 } 59 for(int i=0;i<=n;++i)f[i]=a1[i]; 60 } 61 int solve(){ 62 int mn=1e5,re=0; 63 for(int i=1;i<=n;++i)mn=min(mn,m[i]); 64 for(int i=1,lst;i<=mn;i=lst+1){ 65 int t1=1,t2=0;lst=1e5; 66 for(int j=1;j<=n;++j){ 67 lst=min(lst,m[j]/(m[j]/i)); 68 t1=t1*(m[j]/i)%mod*iv2%mod; 69 } 70 cal(i); 71 for(int j=0;j<=n;++j){ 72 t2=(t2+f[j]*(g[c][j][lst]-g[c][j][i-1])%mod)%mod; 73 // printf("%d ",(g[c][j][lst]-g[c][j][i-1]+mod)%mod); 74 } 75 re=(re+t1*t2%mod)%mod; 76 } 77 return re; 78 } 79 int main(){ 80 #ifndef ONLINE_JUDGE 81 freopen("bzoj3434.in","r",stdin); 82 freopen("bzoj3434.out","w",stdout); 83 #endif 84 pre(); 85 scanf("%d",&T); 86 while(T--){ 87 scanf("%d%d",&n,&c); 88 for(int i=1;i<=n;++i)scanf("%d",&m[i]); 89 printf("%d ",(solve()+mod)%mod); 90 } 91 return 0; 92 }