私は最初のポリア原理について聞いた前NOIP2017ですが、私は将来について考えて学ぶことは難しすぎると思います。
NOIP2018私は、このようなものの審査を考えるために使用さ学ぶために決定され、以降クッション。
WC2019私は、このようなものの審査を考えるために使用さ学ぶために決定され、以降クッション。
SNOI2019私は、このようなものの審査を考えるために使用さ学ぶために決定され、以降クッション。
CTS2019は私は、このようなものの審査を考えるために使用さ学ぶために決定され、以降クッション。
APIO2019私は、このようなものの審査を考えるために使用さ学ぶために決定され、以降クッション。
THUSC2019私は、このようなものの審査を考えるために使用さ学ぶために決定され、以降クッション。
今日から一週間以上NOI2019少なく、私はその後、彼は二つの言葉が終わると、学ぶことが決定した、とすぐに彼は私に言わせjumpmelonつかみました。
.JPG秋
ポリア原理は、私は一時的にメロンの足の学校を保持するので、このブログは、どのようなNOIその次のステートメントの厳格な証明厳格な結論だけではないということですので、 気分を参照してください。 補足。
これらの理由から、このブログTucaoリンクは(コードなし)のテキストよりも長くなることがあります
問題:あります\(N- \)ポイントとリング\(m個\)色、異なる染めカラースキームの自然数を求めて、それぞれが。本質的に異なる二つのプログラムであれば、それらが互いを回転させることによって得ることができない場合のみ。
結論:プログラム番号である(\ \ FRAC {1} { N} \ sum_ {i = 1} ^ NM ^ {\ GCD(N、I)} \)
例:羅区4980ポリアの定理
ダイレクトプッシュルーチンJiuhaola式:
{1} {N} \ [\ {整列}開始ANS&= \ FRAC {1} {N} \ sum_ {i = 1} ^ NN ^ {\ GCD(N、I)} \\&= \ FRAC \ sum_ {D | N} N ^ D \ sum_ {i = 1} ^ {\ FRAC {n}は{D}} [GCD(\ FRAC {n}は{D}、I)= 1] \\&= \ FRAC { 1} {N} \ sum_ {D | N} N ^ Dの\のvarphi(\ FRAC {n}は{D})\ {端整列} \]
するには\(N \)品質係数の分解が、その後によるその要因の全て、品質係数を検索するとき、それを維持するために、\(\ varphi \)がうまく
コード:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
namespace zyt
{
template<typename T>
inline bool read(T &x)
{
char c;
bool f = false;
x = 0;
do
c = getchar();
while (c != EOF && c != '-' && !isdigit(c));
if (c == EOF)
return false;
if (c == '-')
f = true, c = getchar();
do
x = x * 10 + c - '0', c = getchar();
while (isdigit(c));
if (f)
x = -x;
return true;
}
template<typename T>
inline void write(T x)
{
static char buf[20];
char *pos = buf;
if (x < 0)
putchar('-'), x = -x;
do
*pos++ = x % 10 + '0';
while (x /= 10);
while (pos > buf)
putchar(*--pos);
}
typedef long long ll;
typedef pair<int, int> pii;
const int SQRTN = 4e4 + 10, P = 1e9 + 7;
pii prime[SQRTN];
int pcnt, n, ans;
int power(int a, int b)
{
int ans = 1;
while (b)
{
if (b & 1)
ans = (ll)ans * a % P;
a = (ll)a * a % P;
b >>= 1;
}
return ans;
}
int inv(const int a)
{
return power(a, P - 2);
}
void get_prime(int n)
{
pcnt = 0;
for (int i = 2; i * i <= n; i++)
if (n % i == 0)
{
prime[pcnt++] = pii(i, 0);
while (n % i == 0)
++prime[pcnt - 1].second, n /= i;
}
if (n > 1)
prime[pcnt++] = pii(n, 1);
}
void dfs(const int pos, const int mul, const int pmul, const int div)
{
if (pos == pcnt)
{
ans = (ans + (ll)mul / div * pmul * power(n, n / mul)) % P;
return;
}
dfs(pos + 1, mul, pmul, div);
for (int i = 1, tmp = prime[pos].first; i <= prime[pos].second; i++, tmp *= prime[pos].first)
dfs(pos + 1, mul * tmp, pmul * (prime[pos].first - 1), div * (prime[pos].first));
}
int work()
{
int T;
read(T);
while (T--)
{
ans = 0;
read(n);
get_prime(n);
dfs(0, 1, 1, 1);
write((ll)ans * inv(n) % P), putchar('\n');;
}
return 0;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("4980.in", "r", stdin);
#endif
return zyt::work();
}