HH的军训(容斥)

1248: HH的军训

时间限制: 1 Sec  内存限制: 128 MB 提交: 95  解决: 11 [提交][状态][讨论版]

题目描述

大学里,最难忘的事情莫过于军训了,白白的HH童鞋就被无情的晒黑了,话说军训期间,最怕的就是被教官逗了,俗话说:珍爱生命,远离教官。教官总爱让同学们站方阵,由于同学很多,难免会有前面的同学挡着后面的同学,为了远离教官,大家都希望自己站的位置教官看不到自己,现在假如同学们站在一个有坐标点的矩阵上,同学们都站在每一组整数点上,而教官站在坐标(0,0)上,请问此时有多少个位置教官可以直接看到!

输入

第一行输入一个T,代表T组测试数据。

接下来每行输入两个数字M,N,对于任意一个同学的坐标位置(x,y),都有1<=x<=M<=10000,1<=y<=N<=10000.

输出

输出有多少位置教官能够看到。

样例输入

2
1 4
2 3

样例输出

4
5
题解:容斥,少了个等号,错了半天。。。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define mem(x,y) memset(x,y,sizeof(x))
typedef long long LL;
vector<int>p;
void getp(int x){
    for(int i=2;i*i<=x;i++){//太马虎了,错了半天,发现少了个等号。。。。。
        if(x%i==0){
            p.push_back(i);
            while(x%i==0)x/=i;
        }
    }
    if(x>1)p.push_back(x);
}
int getn(int x){
    int sum=0;
    /*for(int i=0;i<p.size();i++){
        cur=p[i];
        sum+=x/cur;
        for(int j=i+1;j<p.size();j++){
            cur*=-p[j];
            sum+=x/cur;
        }
    }*///这种方法不行如果是2,3,4,则2,4选不了。。。。
    for(int i=1;i<(1<<p.size());++i){
        int num=0,mult=1;
        for(int k=0;k<(int)p.size();k++){
            if(i&(1<<k)){
                //1,10,11..1.10.100
                mult*=p[k];
                num++;
            }
        }
        int cur=x/mult;
        if(num&1)sum+=cur;//少了等号。。
        else sum-=cur;
    }
    //printf("%d\n",sum);
    return sum;
}
int main(){
    int T,M,N;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&M,&N);
        int ans=M;
        for(int i=2;i<=N;i++){
            p.clear();
            getp(i);
            ans+=M-getn(M);
        }
        printf("%d\n",ans);
    }
    return 0;
}

  4 6被2 3挡了

 

posted @   handsomecui  阅读(297)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示