Description
给出一个长度为kkk的序列A1,...,AkA_1,...,A_kA1,...,Ak,定义f(m)f(m)f(m)为满足以下条件的CCC序列的数量:
1.若Ai=−1A_i=-1Ai=−1则CiC_iCi可以取[0,m)[0,m)[0,m)中任意整数,否则Ci=Ai%mC_i=A_i\%mCi=Ai%m
2.同余方程∑i=1kCixi≡1(mod m)\sum\limits_{i=1}^kC_ix_i\equiv 1(mod\ m)i=1∑kCixi≡1(mod m)有解
给出一整数nnn,求∑m=1nf(m)\sum\limits_{m=1}^nf(m)m=1∑nf(m)
Input
第一行一整数TTT表示用例组数,每组用例首先输入两个整数k,nk,nk,n,之后输入一长度为kkk的序列AiA_iAi
(1≤T≤250,1≤k≤50,1≤n≤109,−1≤Ai≤109)(1\le T\le 250,1\le k\le 50,1\le n\le 10^9,-1\le A_i\le 10^9)(1≤T≤250,1≤k≤50,1≤n≤109,−1≤Ai≤109)
Output
输出答案,结果模109+710^9+7109+7
Sample Input
2
5 10
-1 -1 8 -1 -1
3 20
-1 6 18
Sample Output
Case #1: 24354
Case #2: 140
Solution
方程有解当且仅当gcd(C,m)=1gcd(C,m)=1gcd(C,m)=1,假设AAA序列中已经确定值的gcdgcdgcd为ggg,尚未确定的数字有xxx个
1.若g≠0g\neq 0g̸=0,记f(d)f(d)f(d)为使得gcd(C,m)=dgcd(C,m)=dgcd(C,m)=d的序列CCC的个数,F(d)F(d)F(d)为使得d∣gcd(C,m)d|gcd(C,m)d∣gcd(C,m)的序列CCC的个数,则显然有
F(d)=(md)x
F(d)=(\frac{m}{d})^x
F(d)=(dm)x
且由F(d)=∑d∣if(i)F(d)=\sum\limits_{d|i}f(i)F(d)=d∣i∑f(i),莫比乌斯反演有
f(1)=∑d∣gcd(g,m)μ(d)F(d)=∑d∣gcd(g,m)μ(d)(md)x
f(1)=\sum\limits_{d|gcd(g,m)}\mu(d)F(d)=\sum\limits_{d|gcd(g,m)}\mu(d)(\frac{m}{d})^x
f(1)=d∣gcd(g,m)∑μ(d)F(d)=d∣gcd(g,m)∑μ(d)(dm)x
进而有
ans=∑m=1n∑d∣gcd(g,m)μ(d)(md)x=∑d∣gμ(d)∑i=1⌊nd⌋ix=∑d∣gμ(d)S(⌊nd⌋,x)
ans=\sum\limits_{m=1}^n\sum\limits_{d|gcd(g,m)}\mu(d)(\frac{m}{d})^x=\sum\limits_{d|g}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}i^x=\sum\limits_{d|g}\mu(d)S(\lfloor\frac{n}{d}\rfloor,x)
ans=m=1∑nd∣gcd(g,m)∑μ(d)(dm)x=d∣g∑μ(d)i=1∑⌊dn⌋ix=d∣g∑μ(d)S(⌊dn⌋,x)
其中S(n,k)=∑i=1ikS(n,k)=\sum\limits_{i=1} i^kS(n,k)=i=1∑ik,通过伯努利序列即可O(k2)O(k^2)O(k2)预处理O(k)O(k)O(k)得到S(n,k)S(n,k)S(n,k),那么该种情况即可O(xg)O(x\sqrt{g})O(xg)解决
2.若g=0g=0g=0,将之前的式子稍作修改有
ans=∑m=1n∑d∣mμ(d)(md)x=∑d=1nμ(d)S(⌊nd⌋,x)
ans=\sum\limits_{m=1}^n\sum\limits_{d|m}\mu(d)(\frac{m}{d})^x=\sum\limits_{d=1}^n\mu(d)S(\lfloor\frac{n}{d}\rfloor,x)
ans=m=1∑nd∣m∑μ(d)(dm)x=d=1∑nμ(d)S(⌊dn⌋,x)
由于⌊nd⌋\lfloor\frac{n}{d}\rfloor⌊dn⌋之后O(n)O(\sqrt{n})O(n)种取值,只要对于每种取值对应的ddd所处区间[l,r][l,r][l,r],知道该区间的μ\muμ之和即可,也即求出莫比乌斯函数前缀和即可
令A(n)=∑i=1nμ(i)A(n)=\sum\limits_{i=1}^n\mu(i)A(n)=i=1∑nμ(i),由于∑i∣dμ(i)=[d=1]\sum\limits_{i|d}\mu(i)=[d=1]i∣d∑μ(i)=[d=1],故有
1=∑d=1n∑i∣dμ(i)=∑i=1nμ(i)⌊ni⌋=∑i=1n∑j=1⌊ni⌋μ(j)=∑i=1nA(⌊ni⌋)
1=\sum\limits_{d=1}^n\sum\limits_{i|d}\mu(i)=\sum\limits_{i=1}^n\mu(i)\lfloor\frac{n}{i}\rfloor=\sum\limits_{i=1}^n\sum\limits_{j=1}^{\lfloor\frac{n}{i}\rfloor}\mu(j)=\sum\limits_{i=1}^nA(\lfloor\frac{n}{i}\rfloor)
1=d=1∑ni∣d∑μ(i)=i=1∑nμ(i)⌊in⌋=i=1∑nj=1∑⌊in⌋μ(j)=i=1∑nA(⌊in⌋)
进而有
A(n)=1−∑i=2nA(⌊ni⌋)
A(n)=1-\sum\limits_{i=2}^nA(\lfloor\frac{n}{i}\rfloor)
A(n)=1−i=2∑nA(⌊in⌋)
同样分块加速即可,小范围前缀和可以线性筛预处理,较大值每次递归记忆化
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=1000005;
#define mod 1000000007
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
int mu[maxn],p[maxn],res=0,vis[maxn],sum[maxn];
void pre(int n=1e6)
{
mu[1]=sum[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])p[res++]=i,mu[i]=-1;
sum[i]=sum[i-1]+mu[i];
if(sum[i]<0)sum[i]+=mod;
for(int j=0;j<res&&i*p[j]<=n;j++)
{
vis[i*p[j]]=1;
if(i%p[j]==0)
{
mu[i*p[j]]=0;
break;
}
mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<=n;i++)
if(mu[i]==-1)mu[i]=mod-1;
}
int inv[60],B[60],C[60][60];
void init(int n=55)
{
C[0][0]=1;
for(int i=1;i<=n;i++)
{
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++)C[i][j]=add(C[i-1][j-1],C[i-1][j]);
}
inv[1]=1;
for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
B[0]=1;
for(int i=1;i<n;i++)
{
for(int j=0;j<i;j++)B[i]=add(B[i],mul(C[i+1][j],B[j]));
B[i]=mod-mul(B[i],inv[i+1]);
}
}
int S(int n,int k)
{
if(k==0)return n%mod;
int ans=0,temp=1;
for(int i=1;i<=k+1;i++)
{
temp=mul(temp,n+1);
ans=add(ans,mul(mul(C[k+1][i],B[k+1-i]),temp));
}
return mul(ans,inv[k+1]);
}
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int get_mu(int n)
{
if(n<=1e6)return mu[n];
int ans=1;
for(int i=2;i*i<=n;i++)
if(n%i==0)
{
int num=0;
while(n%i==0)n/=i,num++;
if(num>1)return 0;
ans*=-1;
}
if(n>1)ans*=-1;
return add(ans,mod);
}
map<int,int>M;
int A(int n)
{
if(n<=1e6)return sum[n];
if(M.find(n)!=M.end())return M[n];
int ans=1;
for(int i=2,nxt;i<=n;i=nxt+1)
{
nxt=n/(n/i);
ans=add(ans,mod-mul(nxt-i+1,A(n/i)));
}
return M[n]=ans;
}
int Solve(int l,int r,int n,int k)
{
if(l==r)return mul(get_mu(l),S(n,k));
return mul(add(A(r),mod-A(l-1)),S(n,k));
}
int Case=1,T,k,n,a[maxn];
int main()
{
pre();
init();
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&k,&n);
int g=0,m=0,ans=0;
for(int i=1;i<=k;i++)
{
scanf("%d",&a[i]);
if(a[i]!=-1)g=gcd(g,a[i]);
else m++;
}
if(g)
{
for(int i=1;i*i<=g;i++)
if(g%i==0)
{
ans=add(ans,Solve(i,i,n/i,m));
if(i*i!=g)ans=add(ans,Solve(g/i,g/i,n/(g/i),m));
}
}
else
{
for(int i=1,nxt;i<=n;i=nxt+1)
{
nxt=n/(n/i);
ans=add(ans,mul(add(A(nxt),mod-A(i-1)),S(n/i,m)));
}
}
printf("Case #%d: %d\n",Case++,ans);
}
return 0;
}