
容斥原理可以画一个韦恩图来看各个集合的关系
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 17;
int p[N];
void solve()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < m; ++ i) cin >> p[i];
int res = 0;
for (int i = 1; i < 1 << m; ++ i)//枚举2的n次方-1个集合
{
int t = 1, cnt = 0;
for (int j = 0; j < m; ++ j)//判断是否乘上p[j]
{
if (i >> j & 1)
{
if ((LL)t * p[j] > n)
{
t = -1;
break;
}
t *= p[j];
cnt ++ ;
}
}
if (t != -1)
{
if (cnt & 1) res += n / t;//奇数就加上,偶数就减去
else res -= n / t;
}
}
cout << res;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}
本题本质上就是一个枚举所有答案的过程,那么我们当然可以用dfs搜索到所有可能的方案
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 17;
int p[N];
int n, m;
int res = 0;
void dfs(int u, int t, bool add)
{
if (u == m)
{
if (t == 1) return ;
else
{
if (add) res += n / t;
else res -= n / t;
return;
}
}
dfs(u + 1, t, add);//m个质数中不选择p[i]
if ((LL)t * p[u] <= n)//m个质数中不选择p[i]
{
dfs(u + 1, t * p[u], !add);//本层选了一个数的话,下一层枚举的集合的add就要取反,因为容斥原理公式就是1个的+,2个的-,3个的+,每多选一个数字,加减号相反
}
}
void solve()
{
cin >> n >> m;
for (int i = 0; i < m; ++ i) cin >> p[i];
dfs(0, 1, false);
cout << res;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}


#include
#include
#include
using namespace std;
const int N = 1e5 + 10;
int a[N];
void solve()
{
int n;
cin >> n;
for (int i = 0; i < n; ++ i) cin >> a[i];
int t = 0;//异或运算里面的0相当于加法里面的0,乘法里面的1
for (int i = 0; i < n; ++ i)
{
t ^= a[i];
}
if (t) cout << "Yes" << endl;
else cout << "No" << endl;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}

#include
#include
#include
#include
#include
using namespace std;
const int N = 1e4 + 10;
int s[N], f[N];//f可以不用,但可以起到剪枝的效果
int n, k;
int sg(int x)
{
if (f[x] != -1) return f[x];
set<int> S;
for (int i = 0; i < k; ++ i)
if(x >= s[i]) S.insert(sg(x - s[i]));//这里如果不判断x>=s[i]的话会影响后续路线的赋值,
//本来下一层应该是1,2但是因为负数,变成了0, 1
//那么本层本来是0的,递归回来的时候现在也会被影响变成了2
for (int i = 0; i < k; ++ i)
{
if (S.count(i) == 0) return f[x] = i;
}
}
void solve()
{
memset(f, -1, sizeof f);
cin >> k;
for (int i = 0; i < k; ++ i) cin >> s[i];
cin >> n;
int x;
int res = 0;
while(n --)
{
cin >> x;
res ^= sg(x);
}
if (res) cout << "Yes" << endl;
else cout << "No" << endl;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}