蹲着还是站着(数论)

链接:https://ac.nowcoder.com/acm/contest/554/H
来源:牛客网
 

杨主席这段时间由于要找实习,所以非常焦躁。因为公司的面试都非常的难,杨主席不知道从哪入手。于是他就找了他的学长坑坑询问情况,坑坑告诉他要注重算法的学习,于是就给杨主席出了一个题目看看他算法学的怎么样,这道题是这样的:有N个人排成一排,从1到N按顺序依次编号,现在要执行N次操作,第一次操作让所有的人都蹲下,之后第二次操作让编号是2和2的倍数的人全部站起来,然后第三次操作让编号是3和3的倍数的人全部做相反的动作(站着的人蹲下,蹲下的人站起来),以此类推...,最后第N此操作让编号为N的这个人也做相反的动作。请问N次操作后,从第A个人到第B个人之间(包括A和B这两个数字,且A<B)有多少人是站着的?

输入描述:

输入数据为T组数据(1<=T<=10)。
每组数据输入包含三个数字N,A,B(1<=N<=1000000,1<=A<B<=N)。

输出描述:

对于每组数据,输出一个整数,表示从第A个人到第B个人之间有多少人站着。

示例1

输入

复制

1
5 1 3

输出

复制

2

方法一:带点技巧的暴力模拟(可能数据比较水)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<list>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int book[N];
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        int n,a,b;
        scanf("%d%d%d",&n,&a,&b);
        for(int i=a; i<=b; i++) book[i]=0;
        for(int i=2; i<=b; i++) {
            for(int j=b/i;i*j>=a;j--){
                book[i*j]^=1;
            }
        }
        int ans=0;
        for(int i=a; i<=b; i++) {
            if(book[i]==1) ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

方法二:

一个正整数n是完全平方数的充分必要条件是n有奇数个因数(包括1和n本身)

即只有完全平方数是蹲着的

#include<iostream>
#include<cmath>
using namespace std;
int  main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,a,b;
        cin>>n>>a>>b;
        int ans=b-a+1;
        for(int i=1;i*i<=b;i++)
        {
            if(i*i>=a)
            {
                ans--;
            }
        }
        cout<<ans<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42936517/article/details/89043615
今日推荐