将m质因子分解,然后枚举选取的质因子个数i进行容斥,每种情况进行一次dfs即可
dfs结束标记:当质因子个数达到i时退出递归,同时累加该解对应的方案数
/* 给定n,m 共有n个数的数组a,不超过m m^n减掉 gcd(a)>1的情况 先把m质因数分解 然后枚举不同的质因子个数即可 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define ll long long ll n,m,p[1005],mm,ans,sum; ll Pow(ll a,ll b){ ll res=1; while(b){ if(b%2)res=res*a; b>>=1;a=a*a; } return res; } void divide(){ mm=0;ll tmp=m; for(int i=2;i*i<=m;i++) if(tmp%i==0){ p[++mm]=i; while(tmp%i==0)tmp/=i; } if(tmp>1)p[++mm]=tmp; } int a[30];//临时数组用来存用到的质因子 void get_sum(int pos,int cnt,int num){ if(cnt>num){//搜出了一组解 ll tmp=m; for(int i=1;i<cnt;i++)tmp/=a[i]; sum+=Pow(tmp,n); return; } for(int i=pos;i<=mm;i++)//枚举下一个位置 a[cnt]=p[i],get_sum(i+1,cnt+1,num); } int main(){ while(cin>>n>>m){ ans=Pow(m,n); divide();//分解质因子m for(int i=1;i<=mm;i++){ sum=0; get_sum(1,1,i); if(i&1) ans-=sum;//关于质因子个数的容斥 else ans+=sum; } cout<<ans<<endl; } }