很多题套在一起的一个东西…
这个
F(x,y)
F
(
x
,
y
)
的type3看起来就很不可做,说明这题只能去枚举
pi,pj
p
i
,
p
j
的组合,去计算他们产生的贡献数
当
pi=pj
p
i
=
p
j
时,也就是我们对于一个出现了
x
x
个的划分方案,要统计他
x(x−1)/2
x
(
x
−
1
)
/
2
次
直接算恰好出现了
x
x
个的划分方案可以用至少出现了
x
x
个的减去至少出现了个的,不过有另一种算法,对于一个至少出现了
x
x
次的划分方案,统计他
x−1
x
−
1
次,然后会发现
∑x−1j=0j=x(x−1)/2
∑
j
=
0
x
−
1
j
=
x
(
x
−
1
)
/
2
令
f[i]
f
[
i
]
为
i
i
个元素的所有集合划分方案数,至少出现了个
i
i
的方案数就是
当
pi≠pj
p
i
≠
p
j
时,可以直接去算至少出现了
x
x
个,
y
y
个的方案数加起来,这样一个恰好
x
x
个,
y
y
个的方案也会被算恰好
xy
x
y
次
第一部分就解决了,第二部分是要快速求
g[i]
g
[
i
]
,
g[i]
g
[
i
]
其实是个积性函数(证明懒得写了网上其他题解有)
有
g[pk]=pg[pk−1]+pk−pk−1
g
[
p
k
]
=
p
g
[
p
k
−
1
]
+
p
k
−
p
k
−
1
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 2005;
const int maxp = 10000005;
const int mod = 1e9+7;
inline void add(int &a,const int &b){ a+=b;if(a>=mod)a-=mod; }
int p[maxp/10],pri,mp[maxp];
int g[maxp];
void get_g()
{
g[1]=1;
for(int i=2;i<maxp;i++)
{
if(!mp[i]) p[++pri]=mp[i]=i,g[i]=2*i-2;
for(int j=1,k=p[j]*i;k<maxp;j++,k=p[j]*i)
{
if(i%p[j]==0)
{
if(mp[i]==i) mp[k]=k,g[k]=(g[k/p[j]]*p[j]+k-k/p[j])%mod;
else mp[k]=mp[i]*p[j],g[k]=(ll)g[i/mp[i]]*g[mp[i]*p[j]]%mod;
break;
}
mp[k]=p[j];
g[k]=(ll)g[p[j]]*g[i]%mod;
}
}
}
int type,n,K;
int f[maxn][maxn],fp[maxn][maxn],fs[maxn];
int pwi[maxn][maxn],Gcd[maxn][maxn];
int g_(int a,int b)
{
if(Gcd[a][b]) return Gcd[a][b];
return Gcd[a][b]=g_(b%a,a);
}
void pre()
{
fs[0]=f[0][0]=1; for(int i=0;i<=n;i++) fp[0][i]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
f[i][j]=fp[i-j][j];
fp[i][j]=(fp[i][j-1]+f[i][j])%mod;
}
for(int j=i+1;j<=n;j++) fp[i][j]=fp[i][i];
fs[i]=fp[i][i];
}
for(int i=1;i<=n;i++)
{
pwi[i][0]=1;
for(int j=1;j<=n;j++) pwi[i][j]=(ll)pwi[i][j-1]*i%K;
}
for(int i=1;i<=n;i++) Gcd[i][0]=Gcd[0][i]=i;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) g_(i,j);
}
int F(int x,int y)
{
if(type==1) return 1;
if(type==2) return Gcd[x][y]%K;
if(type==3) return (pwi[x][y]+pwi[y][x]+(x^y))%K;
return 0;
}
int num[110000],a[110000];
int cal()
{
for(int i=1;i<=n;i++)
{
int cc;
cc=0;
for(int j=1;j*i<=n;j++)
add(cc,(ll)(j-1)*fs[n-j*i]%mod);
add(num[F(i,i)],cc);
for(int j=i+1;i+j<=n;j++)
{
cc=0;
for(int x=1;x*i+j<=n;x++) for(int y=1;x*i+j*y<=n;y++)
add(cc,fs[n-x*i-y*j]);
add(num[F(i,j)],cc);
}
}
int ans=0;
for(int i=0;i<K;i++)
add(ans,(ll)num[i]*g[a[i]]%mod);
return ans;
}
int main()
{
get_g();
scanf("%d%d%d",&type,&n,&K); pre();
for(int i=0;i<K;i++) scanf("%d",&a[i]);
printf("%d\n",cal());
return 0;
}