zoukankan      html  css  js  c++  java
  • “玲珑杯”线上赛 Round #17 河南专场 B:震惊,99%+的中国人都会算错的问题(容斥计算)

    传送门

    题意

    分析

    是一道稍微变形的容斥题目,容斥一般的公式

    [ans=sum_iAi-sum_{i<j}{Ai∩Aj}+sum_{i<j<k}{Ai∩Aj∩Ak}+... ]

    但是这道题只要奇数次数的,那么对于第k项乘以一个系数(2^{k-1})
    具体见代码

    trick

    如果在每次dfs中for循环前加一个判断:if(lcm<=n)...
    时间会从1000ms降到20ms

    代码

    #include<cstdio>
    
    #define ll long long
    #define F(i,a,b) for(int i=a;i<=b;++i)
    #define R(i,a,b) for(int i=a;i<b;++i)
    #define mem(a,b) memset(a,b,sizeof(a))
    //#pragma comment(linker, "/STACK:102400000,102400000")
    //inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}}
    inline ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
    int t,n,m;
    ll lcm,a[16],ans;
    /*
    举个栗子,如A,B,C,那么第一次dfs会计算A,AB,AC,ABC的值,第二次dfs会计算B,BC,第三次dfs会计算C
    ,希望大家能够理解
    */
    void dfs(int cur,ll lcm,int num)//当前第cur个,需要乘的系数为2^(num-1)
    {
    	lcm=a[cur]/gcd(a[cur],lcm)*lcm;
    	if(num&1) ans+=n/lcm*(1ll<<(num-1));
    	else ans-=n/lcm*(1ll<<(num-1));
    	if(lcm<=n) for(int i=cur+1;i<m;++i)  dfs(i,lcm,num+1);
    }
    int main()
    {
        for(scanf("%d",&t);t--;)
        {
        	scanf("%d %d",&n,&m);
        	ans=0;
        	for(int i=0;i<m;++i) scanf("%lld",a+i);
        	for(int i=0;i<m;++i)  dfs(i,a[i],1);
        	printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    addEventListener和attachEvent的区别
    CSS鼠标手势
    css颜色代码大全
    js中showModalDialog的使用
    ajax详解
    JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
    js中Ajax工作原理(转)
    浏览器版本信息判断整理
    常见浏览器User-Agent大全
    JS性能优化之怎么加载JS文件
  • 原文地址:https://www.cnblogs.com/chendl111/p/7074171.html
Copyright © 2011-2022 走看看