HDU 6265Master of Phi 【公式题(欧拉函数)】

xiaoxiao2022-06-11  33

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6265

思路:

首先要确定欧拉函数的一个特例 phi(1) = 1; 在欧拉函数的公式中 phi (n) = n*(1-q1)*(1-q2)*(1-q3)..... 只有n == 1的时候是不适用这个公式的;

其次,题目中要求的公式虽然感觉很复杂,但事实上,只要对公式整理一下,就能发现题目有很多地方是帮你化简了问题的,比如:在公式  phi(3)*n/3 中的分母 3是可以和分子中phi(3)抵消的,因为phi (3) = 3*(1-1/3);所以 phi(3)*n/3 == (1-1/3)*n;这个化简有什么作用?如果phi 没了前面的n,那么phi(6)/6 是等于 phi(36)/36 (只要两个数n1和n2 所包含的素数相同那么 phi(n1)/n1 == phi(n2)/n2);这个问题可以自己通过欧拉函数检验一下;

这里以36为例:

36的因数有  1,2,3,4,6,9,12,18,36;这些数分别用素数的乘积来表示会发现,他们都是由36包含的素数组成;而且2*3组合有2*2个,这两个2分别是 2^2 * 3^2的幂;那么问题就转变成 素数乘积的组合了;

解题方法有两种;

dfs(要用G++交题) 把n的素数个数与对应素数存起来,然后dfs取和不取的情况,就能得到对应的解;

第二种是直接写成公式:

知道欧拉函数的推导过程就不会难理解下面的公式:(+1是能不取这个素数的情况)

下面引用这个博客的图片:https://blog.csdn.net/weixin_38327682/article/details/79988278

#include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; typedef long long ll; const int Mod = 998244353; const int Maxn = 1e8+10; ll inv[Maxn]; int m, ans, p[50], q[50]; //int pow_mod (int a, int n) { // if (n == 0) return 1; // int x = pow_mod (a, n/2); // ll ans = (ll)x*x % Mod; // if (n & 1) ans = ans*a % Mod; // return (int)ans; //} ll pow_mod (int a, int n) { ll ret = 1; while (n) { if (n & 1) ret = ret*a % Mod; a = (ll)a*a % Mod; n >>= 1; } return ret; } void dfs (int step, int sum) { if (step == m) { ans = (ans+sum) % Mod; return; } int t = (ll)sum*(p[step]-1)%Mod*inv[p[step]]%Mod*q[step]%Mod; dfs (step+1, t); dfs (step+1, sum); } int main (void) { int t; scanf ("%d", &t); while (t--) { scanf ("%d", &m); int n = 1; for (int i = 0; i < m; ++i) { scanf ("%d%d", p+i, q+i); n = (ll)n*pow_mod (p[i], q[i]) % Mod; inv[p[i]] = pow_mod (p[i], Mod-2); } ans = 0; dfs (0, n); printf ("%d\n", ans); } return 0; }

第二种:

#include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; typedef long long ll; const int Mod = 998244353; const int Maxn = 1e8+10; //int pow_mod (int a, int n) { // if (n == 0) return 1; // int x = pow_mod (a, n/2); // ll ans = (ll)x*x % Mod; // if (n & 1) ans = ans*a % Mod; // return (int)ans; //} ll pow_mod (int a, int n) { ll ret = 1; while (n) { if (n & 1) ret = ret*a % Mod; a = (ll)a*a % Mod; n >>= 1; } return ret; } int main (void) { int t, m; scanf ("%d", &t); while (t--) { scanf ("%d", &m); ll ans = 1, n = 1, p, q; for (int i = 0; i < m; ++i) { scanf ("%lld%lld", &p, &q); n = n*pow_mod (p, q) % Mod; ans = ans*(q*(p-1)%Mod*pow_mod(p, Mod-2)%Mod+1) % Mod; } ans = ans*n % Mod; printf ("%lld\n", ans); } return 0; }

 

 

转载请注明原文地址: https://www.6miu.com/read-4930282.html

最新回复(0)