首页 > 其他 > 详细

题解——再数17

时间:2019-05-25 16:54:38      阅读:125      评论:0      收藏:0      [点我收藏+]
T2的位置,并不算难,并且是对容斥原理的很好的应用。

题目描述

给你一个有 n个正整数的列An。一个正整数 x 若满足在数列 An 中存在一个正整数 ai,使 x≡17(mod Ai),那么 x 就是一个‘ cost数’。 请问 1到 m的正整数 中, 有多少‘cost?’数?
小 co 看得一头雾水,只好又来请教你

输入

第一行两个 正整数 n和 m,意义见问题描述 。
第二行 n个正整数

输出

1个整数 , 表示 cost 的个数 。

数据范围

n <= 30 , Ai > 17 , m 和 Ai 保证在 int 范围内

题解

考虑容斥原理,我们要找出重复的数量。
提一下,容斥原理是可以从 3 扩展的。
说简单点,就是奇加偶减
开始引用原题解:(此人太懒了)
这时我们需要用个dfs枚举每个ai选与不选,若选出k个数,且k为奇数,则ans加上m/LCM(选出的数),若为偶数ans减去m/LCM(选出的数)。当然,还要加上优化,包括可行性剪枝(选出的数的LCM要小于等于m。由于ai >17,该剪枝十分有效)、优化搜索顺序(先搜大数)。时间复杂度:O(2nlogm)(实际小得多)。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll  N , M , A[ 62 ] , ans ;
inline ll read()
{
    ll s = 0,w = 1;
    char g = getchar();
    while(g<'0'||g>'9'){if(g=='-')w*=-1;g = getchar();}
    while(g>='0'&&g<='9'){s = s*10+g-'0';g = getchar();}
    return s*w;
}
void prepare_(){
    freopen("c17.in","r",stdin);
    freopen("c17.out","w",stdout);
    M = read() , N = read() - 17 ;
    for( register int i = 1 ; i <= M ; i++ )A[ i ] = read() ;
    sort( A + 1 , A + M + 1  ) ;
}
ll  gcd( ll  a , ll  b ){
    return ( b == 0 )?a:gcd( b , a%b ) ;
}
void dfs( ll now , ll h , ll s ){  //  h shows + -
    if( s >= N || now > M ) return ;
    ll t = s / gcd( s , A[ now ] ) * A[ now ] ;
    if ( h % 2 ) ans -= N / t ;
    else ans += N / t ;
    dfs( now + 1 , h + 1 , t ) ;
    dfs( now + 1 , h , s ) ;
}
int main(){
    prepare_();
    if( N < 0 ){ printf("0");return 0 ;}
    if( N == 1 ){ printf("1");return 0 ;}
    else dfs( 1 , 0 , 1 ) ;
    cout << ans + 1 ;
    return 0;
}

有疑惑和建议,可以留下评论或私我。

如果你喜欢我的文章,请点赞支持,谢谢。

题解——再数17

原文:https://www.cnblogs.com/ssw02/p/10922379.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!