51NOD 1262 扔球(欧拉函数)

传送门
1262 扔球
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注
在圆上一点S,扔出一个球,这个球经过若干次反弹还有可能回到S点。N = 4时,有4种扔法,如图:

恰好经过4次反弹回到起点S(从S到T1,以及反向,共4种)。
给出一个数N,求有多少种不同的扔法,使得球恰好经过N次反弹,回到原点,并且在第N次反弹之前,球从未经过S点。
Input
输入一个数N(1 <= N <= 10^9)。
Output
输出方案数量。
Input示例
4
Output示例
4

解题思路:
反弹n次,那起点S,每次反弹点,终点S共连接n+1条边,那么原问题变为从S走n+1条边回到S,设步长为a条边,gcd(a,n+1)==1时,lcm(a,n+1)=a*(n+1),由于a*(n+1)=(n+1)a那么最少走n+1次步长为a的路线才能重合到S;反之gcd(a,n+1)==d时,lcm(a,n+1)=a(n+1)/d,由于关系a*((n+1)/d)=(n+1)*(a/d),最少走(n+1)/d步即反弹(n+1)/d-1

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long LL;
LL Eular(LL m)
{
    LL ans = m;
    for(LL i=2; i*i<=m; i++)
    {
        if(m%i==0)
        {
            ans -= ans/i;
            while(m%i==0)
            {
                m /= i;
            }
        }
    }
    if(m > 1)
        ans -= ans/m;
    return ans;
}
int main()
{
    LL m;
    while(cin>>m)
    {
        cout<<Eular(m+1)<<endl;
    }
    return 0;
}

你可能感兴趣的:(欧拉函数)