正题
大意
画n条线,每次坐标变换为 。给出n,求线穿过的格点数。
解题思路
首先我们想穿过格点的问题,我们可以无视方向,然后每次就当从
到
划一条线。然后我们可以发现穿过的格点数(算上起点)就是
,因为每次都会穿过
这些点。
然后我们可以知道答案就是
但是暴力枚举会超时,我们需要想别的方法
因为要求 ,所以i的个数就是
所以答案就是
由于要求 是整数,所以我们可以化为
然后暴力枚举约数和暴力求欧拉函数值时间复杂度为
代码
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
ll n,ans=1;
ll phi(ll n)//求欧拉函数
{
ll ans=n;
for (ll i=2;i*i<=n;i++)
if (n%i==0)
{
ans=ans/i*(i-1);
while (n%i==0) n/=i;
}
if (n>1) ans=ans/n*(n-1);
return ans;
}
int main()
{
//freopen("beats.in","r",stdin);
//freopen("beats.out","w",stdout);
scanf("%lld",&n);
for (ll i=1;i*i<=n;i++)
{
if (!(n%i))
{
ans+=phi(n/i)*i;
if (i*i!=n) ans+=n/i*phi(i);
}//求约数
}
printf("%lld",ans);
return 0;
}