1 /** 2 題意: 求對於小於m的n個數, 求x1*a1 + x2*a2+x3*a3........+xn*an = 1 3 即求 a1,a2,a3,。。。。an 的最大公約數爲1 , a1,a2....an 可重複 4 原理 : 容斥原理 全部的 排序即 m^n ——不符合的狀況 ,即爲所求 5 不符合的狀況: 就是 這n個數有最大公約數 不是1, 即這n個數是m 的素因子的組合。。 6 一共有 m^n張卡片,若是減去其中含有公約數的卡片剩下的就是所求的結果 7 舉個例子 n=2, m=360; 360=2^3*3^2*5 8 案 = (m ^ n) - (有公因數2的n元組)- (有公因數3的n元組)- (有公因數5的n元組)+ (有公因數2,3的n元組) +(有公因數2,5的n元組) + (有公因數3,5的n元組)- (有公因數2,3,5的n元組)。 9 特殊之處: m^n - (m/2)^n-(m/3)^n........+ (m/2*3)^n+ (m/2*5)^n......-(m/2*3*5)^n 10 -------> m^n(1-1/2^n)(1-1/3^n)(1-1/5^n)...... 11 好像是叫擴展歐拉函數 12 13 **/ 14 #include <iostream> 15 #include <algorithm> 16 #include <cstdio> 17 using namespace std; 18 19 long long pow(long long a,long long b){ 20 long long c =1; 21 while(b){ 22 if(b&1) 23 c = c*a; 24 a =a*a; 25 b>>=1; 26 } 27 return c; 28 } 29 30 long long res(long long n,long long m){ 31 long long sm = pow(m,n); 32 long long ans = m; 33 long long temp ; 34 for(int i=2;i*i<=ans;i++)if(m%i==0){ 35 temp = pow(i,n); 36 sm = sm/temp*(temp-1); 37 while(m%i==0) m /= i; 38 } 39 if(m>1){ 40 temp = pow(m,n); 41 sm = sm/temp*(temp-1); 42 } 43 return sm; 44 45 } 46 int main() 47 { 48 long long n,m; 49 cin>>n>>m; 50 long long s = res(n,m); 51 cout<<s<<endl; 52 return 0; 53 }