• 【NOIP2016提高A组五校联考2】running


    题目

    小胡同学是个热爱运动的好孩子。
    每天晚上,小胡都会去操场上跑步,学校的操场可以看成一个由n个格子排成的一个环形,格子按照顺时针顺序从0 到n- 1 标号。
    小胡观察到有m 个同学在跑步,最开始每个同学都在起点(即0 号格子),每个同学都有个步长ai,每跑一步,每个同学都会往顺时针方向前进ai 个格子。由于跑道是环形的,如果一个同学站在n-1 这个格子上,如果他前进一个格子,他就会来到0。
    他们就这样在跑道上上不知疲倦地跑呀跑呀。小胡同学惊奇地发现,似乎有些格子永远不会被同学跑到,他想知道这些永远不会被任何一个同学跑到的格子的数目,你能帮帮他
    吗?(我们假定所有同学都跑到过0 号格子)。

    分析

    首先对于一个人 i, 显然,那么它所能到达的格子一定是$gcd(ai,n) (的倍数。 所以我们枚举n的约数d,如果有一个i,)gcd(a_i,n)|d(,说明所有)gcd(j,n) = d$ 的格子都能被到达,答案加上 (φ(dfrac{n}{d})) 即可。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=55;
    using namespace std;
    int a[N],n,m,ans;
    int gcd(int x,int y)
    {
        if(y==0) return x;    
        if(x<y) return gcd(y,x);    
        else return gcd(y, x%y); 
    }
    int phi(int x)
    {
    	int sum=x,e=x;
    	for(int i=2;i<=int(sqrt(e));i++)
    	{
    		if(x%i==0)
    		{
    			sum=sum/i*(i-1);
    			while(x%i==0) x/=i;
    		}
    	}
    	if(x>1)
    	{
    		sum=sum/x*(x-1);
    	}
    	return sum;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++) scanf("%d",&a[i]);
    	for(int i=1;i<=int(sqrt(n));i++)
    	{
    		if(n%i==0)
    		{
    		for(int j=1;j<=m;j++)
    			if(i%gcd(a[j],n)==0)
    			{
    				ans+=phi(n/i);
    				break;
    			}
    		for(int j=1;j<=m;j++)
    			if((n/i)%gcd(a[j],n)==0)
    			{
    				ans+=phi(i);
    				break;
    			}
    		}
    	}
    	cout<<n-ans<<endl;
    }
    
    
  • 相关阅读:
    使用RecyclerView打造Gallery
    Retrofit简介与使用方法(翻译)
    迷宫实现递归版本C++
    牛客笔试题
    牛客笔试题---求最长重复词长度之和
    C++句柄解析
    C++双向循环链表实现
    String C++完整实现。
    String写时拷贝实现
    顺序表操作补充(查找方法增加)
  • 原文地址:https://www.cnblogs.com/chen1352/p/9065037.html
Copyright © 2020-2023  润新知