题意实质是 求给出了n和m,要求出满足最大公约数(x1,x2,...,xn,m)=1的x1,...,xn的组数sum,其中必须满足0<= x1,x2,...,xn <= m。
先求出 sum = m^n 然后减去 最大公约数>1的组数 即求出m的所有约数
对于每个约数fac[i] 每个x有m/fac[i]种选择
再根据容斥原理 减去由奇数个质因子组成的约数 加上由偶数个质因子组成的约数
本题应用大数 不过long long能过
代码如下
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
struct data
{
int num,v;
bool operator <(const data &p)const
{
return num<p.num;
}
}fac[50];
ll mypow(int m,int n)
{
ll ans=1;
while(n--)
{
ans*=m;
}
return ans;
}
int find_factor(int m)
{
int i,j,cnt;
cnt=0;
for(i=2;i*i<m;i++)
{
if(m%i==0)
{
fac[cnt++].num=i;
fac[cnt++].num=m/i;
}
}
if(i*i==m)
{
fac[cnt++].num=i;
}
fac[cnt++].num=m;
sort(fac,fac+cnt);
for(i=0;i<cnt;i++)
{
bool prime=true;
int k=0;
for(j=0;j<i;j++)
{
if(fac[j].v==1&&fac[i].num%fac[j].num==0)
{
k++;
prime=false;
if(fac[i].num%(fac[j].num*fac[j].num)==0)
{
k=0;
break;
}
}
}
if(prime)
{
fac[i].v=1;
}
else
{
fac[i].v=k;
}
}
return cnt;
}
int main()
{
int n,m,i,cnt;
while(~scanf("%d%d",&n,&m))
{
cnt=find_factor(m);
ll sum=mypow(m,n);
for(i=0;i<cnt;i++)
{
if(fac[i].v==0)
{
continue;
}
else if(fac[i].v%2==1)
{
sum-=mypow(m/fac[i].num,n);
}
else
{
sum+=mypow(m/fac[i].num,n);
}
}
printf("%lld\n",sum);
}
return 0;
}
981

被折叠的 条评论
为什么被折叠?



