1138 - 震惊,99%+的中国人都会算错的问题(容斥变型)

DESCRIPTION 众所周知zhu是一个大厨,zhu一直有自己独特的咸鱼制作技巧. tang是一个咸鱼供应商,他告诉zhu在他那里面有N条咸鱼(标号从1到N)可以被用来制作.每条咸鱼都有一个咸鱼值Ki,初始时所有Ki都是0 zhu是一个特别的人,他有M个咸数(咸鱼数字), 对于每个咸数x,他都会让所有满足标号是x倍数的咸鱼的咸鱼值异或上1.zhu现在想知道经过了这M个咸数的筛选之后,最终有多少条的咸鱼的咸鱼值是1? INPUT 输入的第一行包含一个整数T(1≤T≤1000),表示有T组数据. 对于每组数据: 输入第一行只有两个整数N(1≤N≤10^9),M(1≤M≤15). 接下来一行有 M M个整数,依次对应zhu的每个咸数(1≤咸数≤2∗105). OUTPUT 对于每组数据,输出答案.
SAMPLE INPUT 2 10 1
3 10 1 1
SAMPLE OUTPUT
3 10

很明显是个容斥,可惜具体不会。。 然后画个图,找规律,

这个题是很经典的容斥啊,不过我以前做的是容斥是统计所有格子的,这个容斥需要统计奇数个的数字个数,两个相同的数异或为0

所以我就要对之前的容斥进行修改,比如A BC,我以前是 A+B+C-AC-AB-BC+ABC,现在我需要做的是A+B+C-2AC-2AB-2BC+4ABC,和我当前id有关,2的几次幂,然后就可以过了 就是把两个合并的都删掉了 接着 中间的小部分 3-2-2-2+4=1。

#include <bits/stdc++.h>
using namespace std;
long long ans,a[30];
int n,m;

long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}

void dfs(int cur,long long lcm,int id)
{
    lcm=a[cur]/gcd(a[cur],lcm)*lcm;
    if(id&1)
        ans+=n/lcm*(1<<(id-1));
    else ans-=n/lcm*(1<<(id-1));
    if(lcm<=n)
    for(int i=cur+1;i<m;i++)
        dfs(i,lcm,id+1);
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ans=0;
        cin>>n>>m;
        for(int i=0;i<m;i++)
            cin>>a[i];
        for(int i=0;i<m;i++)
            dfs(i,a[i],1);
        cout<<ans<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值