容斥原理
输入格式
第一行包含整数 N
第二行包含三个整数,表示约翰设置的密码组合。
第三行包含三个整数,表示制造商设置的密码组合。
输出格式
输出一个整数,表示可以打开锁的密码组合数量。
数据范围
1≤N≤100
输入样例:
50
1 2 3
5 6 7
输出样例:
249
题解
距离为2理解: 三个位置,每个位置都是距离为2以内,注意0与n相邻的循环(可以用mod进行处理)
- 首先若n<=5,则密码锁中任何一个组合一定都与两个密码在距离为2之中,都可以打开,则必定只有nnn种方式
- 首先将3个密码锁位的距离为2数字记录在集合 a b c。若两个密码的所有可打开组合不相交,则有250种(2*5*5*5);若相交,三个集合中就有数量少于10,最终组合数=250-a相交的部分*b相交的部分*c相交的部分
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <set>
using namespace std;
int main()
{
int n;
cin>>n;
set<int> a,b,c;
int x,y,z;
/* 输入约翰密码和制造商密码并将每个密码位前后距离为2以内的五个数加入到集合 */
for(int k = 0; k < 2; ++k){
cin>>x>>y>>z;
for(int i = -2; i < 3; ++i)
{
a.insert((x + n + i) % n); // 注意x+i为负数时候也mod正确
b.insert((y + n + i) % n);
c.insert((z + n + i) % n);
}
}
/* 若n小于等于5,则密码锁任意一个组合都可以打开 */
if(n<=5) cout<<n*n*n<<endl;
else
{
/*
若两个密码的所有课打开组合不想交,则有250种(2*5*5*5)
若相交,则在集合 a b c三个中就有数量少于10,
最终组合数=250-a相交的部分*b相交的部分*c相交的部分
*/
cout<<250 - (10 - a.size()) * (10 - b.size()) * (10 - c.size());
}
return 0;
}