Description
小胡同学是个热爱运动的好孩子。
每天晚上,小胡都会去操场上跑步,学校的操场可以看成一个由n 个格子排成的一个环形,格子按照顺时针顺序从0 到n-1 标号。
小胡观察到有m 个同学在跑步,最开始每个同学都在起点(即0 号格子),每个同学都有个步长ai,每跑一步,每个同学都会往顺时针方向前进ai 个格子。由于跑道是环形的,如果一个同学站在n-1 这个格子上,如果他前进一个格子,他就会来到0。
他们就这样在跑道上上不知疲倦地跑呀跑呀。小胡同学惊奇地发现,似乎有些格子永远不会被同学跑到,他想知道这些永远不会被任何一个同学跑到的格子的数目,你能帮帮他吗?(我们假定所有同学都跑到过0 号格子)。
Input
第一行两个整数n,m。
接下来一行有m 个正整数,代表a1; a2……am
Output
输出一个整数,代表永远不会被同学跑到的格子的数目。
Sample Input
6 1
2
Sample Output
3
Data Constraint
对于30% 的数据,1<=n<=100
对于60% 的数据,1<=n<=10^6
对于100% 的数据,1<=n<=10^9; 1<=m<=50; 1<=ai<=n
正解
对于每一个人i,他可以走到的格子一定是gcd(ai,n)的倍数。
所以我们枚举n的约数d,如果有一个i,gcd(ai,n)|d,说明所有gcd(j,n)=d 的格子都能被到达,答案加上φ(nd)即可。
(部分题解摘录自jzoj《NOIP2016 模拟题题解》)
code(原谅本人P党)
var
n,m,i,j,ans:longint;
a:array[0..60]of longint;
function phi(k:longint):longint;
var
i,j:longint;
begin
phi:=k;j:=k;
i:=2;
while sqr(i)<=j do begin
if j mod i=0 then begin
phi:=phi*(i-1) div i;
while (j mod i=0) do j:=j div i;
end;
inc(i);
end;
if j>1 then phi:=phi div j*(j-1);
end;
function gcd(x,y:longint):longint;
begin
if x mod y=0 then
exit(y)
else
exit(gcd(y,x mod y));
end;
begin
assign(input,'running.in');reset(input);
assign(output,'running.out');rewrite(output);
readln(n,m);
for i:=1 to m do read(a[i]);
for i:=1 to trunc(sqrt(n)) do begin
if (n mod i=0) then begin
for j:=1 to m do
if (i mod gcd(a[j],n)=0) then begin
ans:=ans+phi(n div i);
break;
end;
if (n div i<>i) then begin
for j:=1 to m do
if (n div i) mod gcd(a[j],n)=0 then begin
ans:=ans+phi(i);
break;
end;
end;
end;
end;
writeln(n-ans);
close(input);
close(output);
end.