容斥原理水题选做

来源:互联网 发布:fanuc数控系统图纸编程 编辑:程序博客网 时间:2024/06/06 16:40

今天wxhRound考了一道不能再简单的容斥,完全做不来,感觉容斥很弱


[UVA10325] The Lottery


题意:求1~n中不能被给定m个数中任意一个数整除的数的个数


答案就是n-(被m个数中任意一个数整除的数的个数)
后面这个算法就是:
被1个数整除的数的个数-被2个数整除的数的个数+被3个数整除的数的个数。。。。。。。

容斥实现方法:二进制压位暴力

我怀疑此题数据不合法,a[i]用%lld读入才AC

#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#include <bitset>#include <queue>#include <set>#include <map>using namespace std;typedef long long ll;ll n, m, a[20], ans;ll gcd( ll a, ll b ){ return b == 0 ? a : gcd( b, a%b ); }int main(){while( scanf( "%d%d", &n, &m ) != EOF ){for( int i = 1; i <= m; i++ ) scanf( "%lld", &a[i] );ans = n;for( int i = 1; i < (1<<m); i++ ){ll ret = 1, cnt = 0;for( int j = 1; j <= m; j++ )if( i & (1<<(j - 1)) ){cnt++;ret = ret * a[j] / gcd( ret, a[j] );if( ret > n ) break;}if( ret > n ) continue;ret = n / ret;if( cnt & 1 ) ans -= ret; else ans += ret;}printf( "%lld\n", ans );}return 0;}
[UVA11806] 

Cheerleaders

 

题意:n*m的矩阵,放k个东西。

要求第1,n行 第1,n列必须有的方案数

答案就是所有的-少一行或一列+少两行或一列。。。


容斥实现方法:二进制压位暴力


#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#include <bitset>#include <queue>#include <set>#include <map>using namespace std;int T, n, m, C[405][405], K;const int mod = 1000007;int main(){for( int i = 0; i <= 400; i++ ){C[i][i] = C[i][0] = 1;for( int j = 1; j < i; j++ )C[i][j] = ( C[i - 1][j] + C[i - 1][j - 1] ) % mod;}scanf( "%d", &T );for( int cas = 1; cas <= T; cas++ ){scanf( "%d%d%d", &n, &m, &K );int ans = 0;for( int i = 0; i < 16; i++ ){int r = n, c = m, cnt = 0;if( i & 1 ){ r--; cnt++; }if( i & 2 ){ r--; cnt++; }if( i & 4 ){ c--; cnt++; }if( i & 8 ){ c--; cnt++; }if( cnt & 1 ) ans = ( ans - C[r*c][K] + mod ) % mod;else ans = ( ans + C[r*c][K] ) % mod;}printf( "Case %d: %d\n", cas, ans );}return 0;}

[poj3904]给出n个数,从其中选出4个数,使它们的最大公约数为1,问总共有多少中取法。


答案明显就是:所有排列-1个素数倍数的数+3个素数倍数的数-2个素数倍数的数。。。。

直接考虑容斥绝对过不了

对于每一个数进行质因数分解,最多有6个质因子,可以容斥,把这个数的因数容斥出来

然后答案统计一下就好了


容斥实现方法:二进制压位暴力

ps:此题用莫比乌斯函数也行,但是没必要

#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#include <bitset>#include <queue>#include <set>#include <map>using namespace std;typedef long long ll;int tot, pri[10], n, a[10005], one[10005], cnt[10005]; ll fac[10005], ans;void init(){ans = 0;memset( cnt, 0, sizeof(cnt) );memset( one, 0, sizeof(one) );}void solve( int x ){memset( pri, 0, sizeof(pri) ); tot = 0;for( int i = 2; i * i <= x; i++ )if( x % i == 0 ){pri[++tot] = i;while( x % i == 0 ) x /= i;}if( x != 1 ) pri[++tot] = x;for( int i = 1; i < (1<<tot); i++ ){int k = 1, num = 0;for( int j = 0; j < tot; j++ )if( (1<<j) & i ){k *= pri[j + 1];num++;}cnt[k]++;one[k] = num;}}int main(){for( int i = 4; i <= 10000; i++ ) fac[i] = 1LL * (i - 3) * (i - 2) * (i - 1) * i / 24;while( ~scanf( "%d", &n ) ){init();for( int i = 1; i <= n; i++ ) scanf( "%d", &a[i] ), solve( a[i] );for( int i = 1; i <= 2500; i++ )if( cnt[i] ){if( one[i] & 1 ) ans -= fac[cnt[i]];else ans += fac[cnt[i]];}printf( "%lld\n", ans + fac[n] );}return 0;}
spoj 4168. Square-free integers
求出1~n中不能被“完全平方数”(不含1)整除的数的个数。


我乱想的,搜题解结果(以上)是对的

容斥方法:莫比乌斯函数

#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#include <bitset>#include <queue>#include <set>#include <map>using namespace std;const int N = 10000000 + 5;typedef long long ll;ll ans, n;int mul[N], tot, pri[1000005], T; bool isnot[N];void mobius(){for( int i = 2; i <= 10000000; i++ ){if( !isnot[i] ) pri[++tot] = i, mul[i] = -1;for( int j = 1; j <= tot && i * pri[j] <= 10000000; j++ ){isnot[i * pri[j]] = 1;if( i % pri[j] == 0 ) mul[i * pri[j]] = 0;else mul[i * pri[j]] = mul[i] * -1;}}}int main(){mobius();scanf( "%d", &T );while( T-- ){scanf( "%lld", &n );ans = n;for( ll i = 2; i * i <= n; i++ )ans += mul[i] * n / i / i;printf( "%lld\n", ans );}return 0;}


原创粉丝点击