Atcoder Beginer Contest 162 E - Sum of gcd of Tuples (Hard)

Atcoder Beginer Contest 162 E - Sum of gcd of Tuples (Hard)

一.题目大意
N N N个数,每一个数都在 [ 1 , K ] [1,K] [1,K]之间,共有 K N K^N KN种不同的排列,对于每一种排列求 g c d gcd gcd,把每个 g c d gcd gcd加起来,模 1 0 9 + 7 10^9+7 109+7
二.大体思路
不能暴力,否则~~~
考虑对于 x x x的情况:
g c d ( A 1 , A 2 , . . . , A N ) = x gcd(A_1,A_2,...,A_N)=x gcd(A1,A2,...,AN)=x
满足( k i 表 示 x 是 A i 的 k i 倍 k_i表示x是A_i的k_i倍 kixAiki):
A 1 = x k 1 , A 2 = x k 2 , . . . , A N = x k N A_1=xk_1,A_2=xk_2,...,A_N=xk_N A1=xk1,A2=xk2,...,AN=xkN
每一个 k i k_i ki共有 [ K / x ] [K/x] [K/x]种取值,一共有 N N N个,所以有 [ K / x ] N [K/x]^N [K/x]N中排列方式。
不过,这样会挂~~
因为不能全是 x x x的倍数的倍数,所以要减掉 x = x 的 倍 数 的 倍 数 的 情 况 x=x的倍数的倍数的情况 x=x
即若 y y y x x x的倍数(不是 x x x),则要减掉 y y y的情况数(可以用 a n s y ans_y ansy存储)
三.上代码!!!

#include "bits/stdc++.h"
using namespace std;
const int maxN=1e5+10;
const long long MOD=1e9+7;
int n;
long long k;
long long ans[maxN];
long long res=0LL;
long long fast_mi(long long a,int p)
{
	if(p==0)
	{
		return 1LL;
	}
	long long tmp=fast_mi(a,p>>1);
	tmp=tmp*tmp%MOD;
	if(p&1)
	{
		tmp=tmp*a%MOD;
	}
	return tmp;
}
int main()
{
	cin>>n>>k;
	for(long long x=k;x>=1LL;x--)
	{
		long long multi_num=k/x;
		long long num=fast_mi(multi_num,n);
		for(int i=x+x;i<=k;i+=x)
		{
			num=(num-ans[i]+MOD)%MOD;
		}
		ans[x]=num;
		res=(res+num*x)%MOD;
	}
	cout<<res<<endl;
	return 0;
}

EOF

你可能感兴趣的:(AtCoder)