版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/82947042
正题
题目大意
给出
求
的方案个数
的值
解题思路
表示前i个数的乘积和k的最大公约数为k的第j个约数时的方案个数。
动态转移方程:
为k的第i个约数,
为i是k的第几个约数。
然后我们考虑如何求出
内有多少个数与k的最大公约数为k的第i个约数
也就是
首先
(数论基础)
我们可以考虑用容斥,我们将重复偶数次的减去,重复奇数次的加上。
之后预处理一下
的情况就好了。
code
#pragma GCC optimize(2)
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
%:pragma GCC optimize("-fgcse")
%:pragma GCC optimize("-fgcse-lm")
%:pragma GCC optimize("-fipa-sra")
%:pragma GCC optimize("-ftree-pre")
%:pragma GCC optimize("-ftree-vrp")
%:pragma GCC optimize("-fpeephole2")
%:pragma GCC optimize("-ffast-math")
%:pragma GCC optimize("-fsched-spec")
%:pragma GCC optimize("unroll-loops")
%:pragma GCC optimize("-falign-jumps")
%:pragma GCC optimize("-falign-loops")
%:pragma GCC optimize("-falign-labels")
%:pragma GCC optimize("-fdevirtualize")
%:pragma GCC optimize("-fcaller-saves")
%:pragma GCC optimize("-fcrossjumping")
%:pragma GCC optimize("-fthread-jumps")
%:pragma GCC optimize("-funroll-loops")
%:pragma GCC optimize("-fwhole-program")
%:pragma GCC optimize("-freorder-blocks")
%:pragma GCC optimize("-fschedule-insns")
%:pragma GCC optimize("inline-functions")
%:pragma GCC optimize("-ftree-tail-merge")
%:pragma GCC optimize("-fschedule-insns2")
%:pragma GCC optimize("-fstrict-aliasing")
%:pragma GCC optimize("-fstrict-overflow")
%:pragma GCC optimize("-falign-functions")
%:pragma GCC optimize("-fcse-skip-blocks")
%:pragma GCC optimize("-fcse-follow-jumps")
%:pragma GCC optimize("-fsched-interblock")
%:pragma GCC optimize("-fpartial-inlining")
%:pragma GCC optimize("no-stack-protector")
%:pragma GCC optimize("-freorder-functions")
%:pragma GCC optimize("-findirect-inlining")
%:pragma GCC optimize("-fhoist-adjacent-loads")
%:pragma GCC optimize("-frerun-cse-after-loop")
%:pragma GCC optimize("inline-small-functions")
%:pragma GCC optimize("-finline-small-functions")
%:pragma GCC optimize("-ftree-switch-conversion")
%:pragma GCC optimize("-foptimize-sibling-calls")
%:pragma GCC optimize("-fexpensive-optimizations")
%:pragma GCC optimize("-funsafe-loop-optimizations")
%:pragma GCC optimize("inline-functions-called-once")
%:pragma GCC optimize("-fdelete-null-pointer-checks")
#include<cstdio>
#include<cmath>
#include<algorithm>
#define BPM 10007
#define N 4010
using namespace std;
int n,m,k,frct,prit,fft[N],sum,m1;
int pri[N],frc[N],ff[N][N],ys[10000001],f[N][N];
void dfs(int x,int zf,int ans)//容斥
{
if(x>prit) {
sum+=m1/ans*zf;
return;
}
dfs(x+1,zf,ans);
dfs(x+1,-zf,ans*pri[x]);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
int sk=sqrt(k);
for(int i=1;i<=sk;i++)
{
if(k%i==0)
{
frc[++frct]=i;
if(k/i>sk) frc[++frct]=k/i;
}
}//求约数
sort(frc+1,frc+1+frct);
int tmp=k;
for(int i=2;i<=sk;i++)
{
if(tmp==1) break;
if(tmp%i==0)
{
pri[++prit]=i;
while(tmp%i==0) tmp/=i;
}
}//求质因子
if(tmp!=1) pri[++prit]=tmp;
sort(pri+1,pri+tmp+1);
for(int i=1;i<=frct;i++)
{
ys[frc[i]]=i;
sum=0;m1=m/frc[i];
dfs(1,1,1);
f[1][i]=sum%BPM;
}//计算f[1]
for(int i=1;i<=frct;i++)
for(int j=1;j<=i;j++)
if(frc[i]%frc[j]==0)
ff[i][++fft[i]]=j;//预处理关系
for(int i=2;i<=n;i++)
for(int j=1;j<=frct;j++)
{
if(!fft[j]) continue;
for(int k=1;k<=fft[j];k++)
f[i][j]=(f[i][j]+f[i-1][ff[j][k]]*f[1][ys[frc[j]/frc[ff[j][k]]]])%BPM;
//动态转移
}
printf("%d",f[n][frct]);
}