Discription
Doが、あなたは考えると1つのACMコンテストの後、これらの未解決の問題を解決しようとするいくつかの時間を費やしていますか?
番号?あなたが「ビッグ牛」になりたいときああ、あなたはこれを行う必要があります。
今、あなたは、この問題は非常に精通していることがわかります:
時々 (a、b)が書かれた最大公約数GCD 2つの正の整数aとbの(a、b)は、最大の除数に共通のaとbです。例えば、(1、2)= 1、(12、18)6 = (B)は、容易にユークリッドアルゴリズムにより求めることができます。今、私はもう少し難しい問題を検討しています:
整数Nを考えると、整数M(0 <M <N)を満たす(N、M)> 1の数をカウントしてください。
私はこの問題に名前を付けるように、これは、あなたはまだそれを解決することはできません.IF、研究のあなたの方法を考える良いをしてください「GCDアゲイン」、あなたが最近コンテストで行われてきた問題「GCD」の簡易版です。
幸運を!
入力
入力は複数のテストケースが含まれています。各テストケースは、整数N(1 <N <100000000)を含みます。0を含むテストケースは、入力を終了し、このテストケースは、処理されるべきではありません。
出力
各整数のN君が出力する整数の数は1行で、入力の各ラインの出力の1行でMなければなりません。
サンプル入力
2
4
0
サンプル出力
0
1
問題の意味
Nの所与の
M(0 <M <N)の条件における要求
(N、M)> 1設立の数
アイデアは
、それを変更していない長い時間のために書くかのユニークな分解定理[+]と除外の定理を使用したい、問題はもっと複雑だと思うようになりました。
その後、Nが素数でない数を求めているの数の問題は、それが直接素数オイラー関数を決定し、その後、N-1と番号の素数を差し引くことができることを意味し、発見しました。
ACコード
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
///直接求解一个数n的欧拉函数
int euler(int n){ //返回euler(n)
int res=n,a=n;
for(int i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
int n;
int main()
{
while(scanf("%d",&n)!=EOF&&n)
{
printf("%d\n",n-euler(n)-1);
}
return 0;
}