Fernando won a compass for his birthday, and now his favorite hobby is drawing stars: first, he marks N points on a circumference, dividing it into N equal arcs; then, he connects each point to the k-th next point, until returning to the first point.
Depending on the value of k, Fernando may or may not reach all points marked on the circumference; when that happens, the star is called complete. For example, when N = 8, the possible stars are shown in the figure below. Stars (a) and (c) are complete, while stars (b) and (d) are not.
Depending on the value of N, it may be possible to draw many different stars; Fernando asked you to write a program that, given N, determines the number of complete stars he can draw.
Input
The input contains several test cases. Each test case contains a single line, containing a single integer N (3 ≤ N < 231), indicating the number of arcs in which the circumference was divided.
Output
For each test case, your program must print a single line containing a single integer, indicating the number of complete stars that can be drawn.
Example
Input: 3
4
5
18
36
360
2147483647 Output: 1
1
2
3
6
48
1073741823
题意:给出一个圆,圆上有n个点,以任一点为起点,每次可以向一个方向连到第k个点(距离本身),问有多少种连法,可以吧所有的点都连上
思路:画图可以简单的归纳出,每次向前的点数k,必须符合gcd(k,n)=1,才能把所有点都连上
又因为呢 向前k个点和向前(n-k)个点的方法其实是一样的因此总的方法数就是小于n且与n互质得数的个数除以2;
也就是欧拉函数 euler(n)/2;
起初做这道题的时候以为是道规律题,找了半天规律,自找对了n为偶数的情况,奇数一直以为直接初二(其实是质数直接除二,怪自己找的样例太个别)
#include <iostream> #include <cstdio> #include <string> #include <algorithm> #include <map> #define Mod 1000000007 using namespace std; typedef long long ll; const ll N = 3000000+10; map<ll,ll> elh; long long a,b; ll sum [N]; ll Euler(ll n) { ll res =n; for(ll i=2;i<=n/i;i++) { if(n%i==0) { res = res -res/i; } while(n%i==0)n/=i; } if(n>1)res -= res/n; return res; } int main() { while(~scanf("%lld",&a)) { cout <<Euler(a)/2<<endl; } return 0; }