905
作者:互联网
emmmmm, 这是一次比较有意义的题吧, 最后我的排名很靠前, 但是成绩也不是很如人意。。。
这是第一道题, 一般会比较简单一点, 但却是我三道题中得分最低的一个, 只有30分的暴力分。 当时写的时候直接暴力搜索, 选出所有的情况并记录, 复杂度为 O(T · 2 n )。
我们先看k = 2的特例, 我们可以想到, 在n个位置中放m的小球, 且小球的间距 >= 1, 即留出一个间隔。假设我们就在前m个位置上放上小球而此时的方案数是C(m - 2,n - 2 - (m - 1) ), (C为组合数),
那我们就推广到k的做法, 即0两个球之间间距 >= k - 1, 方案数为C(m - 2, n - 2 - (m - 1)* (k - 1)),由于只用判断方案数的奇偶性, 由卢卡斯定理可得, 在%p的情况下, C(n, m) = C(n % p, m % p)* C(n / p, m / p);当p = 2时, C(n, m)共有4种情况, 当m >= n 时, C(n, m) = 1; 所以用卢卡斯定理继续递归下去, 当m & n = n, (即n的每一位的1在m中都是1),则C(n, m)的结果为1, 否则为0; 所以该题的正解就是判断((n - 2 - (m - 1) * (k - 1)) & (m - 2)) == m - 2是否成立。
#include <bits/stdc++.h> using namespace std; template < typename T > inline void read(T &x) { x = 0; T ff = 1, ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } x *= ff; } int T, n, m, k; int main() { read(T); while(T--) { read(n); read(m); read(k); if(((n - 2 - (m - 1) * (k - 1)) & (m - 2)) == m - 2) puts("Yes"); else puts("No"); } return 0; }正解
#include <bits/stdc++.h> using namespace std; template < typename T > inline void read(T &x) { x = 0; T ff = 1, ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } x *= ff; } int T, n, m, k; bool ans = false; void dfs(int now, int val) { if(now == m + 1) { if(val == n) ans ^= 1; return ; } for(int i = n - (m - now) * k - val; i >= k; --i) { if(now == m && val + i < n) continue; dfs(now + 1, val + i); } } int main() { freopen("phantasm.in", "r", stdin); freopen("phantasm.out", "w", stdout); read(T); while(T--) { read(n); read(m); read(k); dfs(2, 1); if(ans) puts("Yes"); else puts("No"); ans = false; } return 0; }搜素大法好(30分)
emmmm,题目就省略了
标签:ch,905,read,while,ff,isdigit,getchar 来源: https://www.cnblogs.com/AK-ls/p/11481683.html