@一句话题解 - 2020.03@
作者:互联网
咕咕咕。
这些题目倒不一定是我 3 月才做的,有可能是我之前做了现在才写的题解。
topcoder - SRM545D1L3:按位考虑,除非该位全是 1,否则两边必须各自至少有一个 0。容斥哪些位有一边全为 1,利用并查集算出结果。
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
class SetAndSet{
public:
int a[20][50], cnt[20], fa[20][50];
int find(int t, int x) {return fa[t][x] = (fa[t][x] == x ? x : find(t, fa[t][x]));}
bool unite(int t, int x, int y) {
int fx = find(t, x), fy = find(t, y);
if( fx != fy ) {
fa[t][fx] = fy;
return true;
}
else return false;
}
ll ans; int n;
void dfs(int d, int k, int f) {
if( d == 20 ) {
ans += f*((1LL << k) - 2);
return ;
}
if( d )
for(int i=0;i<n;i++) fa[d][i] = fa[d-1][i];
else for(int i=0;i<n;i++) fa[d][i] = i;
dfs(d + 1, k, f);
if( cnt[d] ) {
for(int i=1;i<cnt[d];i++)
if( unite(d, a[d][0], a[d][i]) ) k--;
dfs(d + 1, k, -f);
}
}
ll countandset(vector<int>A) {
n = A.size();
for(int i=0;i<20;i++) {
cnt[i] = 0;
for(int j=0;j<n;j++)
if( !((A[j] >> i) & 1) ) a[i][cnt[i]++] = j;
}
dfs(0, n, 1);
return ans;
}
};
ZOJ - 4064:考虑容斥,枚举哪些格子禁止覆盖。只有相邻禁止覆盖的格子才有贡献,所以记 dp[i][j] 表示最近一个禁止覆盖位置为 i,有 j 个可以选择覆盖的区间的方案数*容斥系数,转移随便做。本题有点卡常。
#include <cstdio>
const int MAXN = 100;
const int MOD = int(1E9) + 7;
inline int add(int x, int y) {return (x + y >= MOD ? x + y - MOD : x + y);}
inline int sub(int x, int y) {return (x - y < 0 ? x - y + MOD : x - y);}
inline int mul(int x, int y) {return 1LL * x * y % MOD;}
int pow_mod(int b, int p) {
int ret = 1;
for(int i=p;i;i>>=1,b=mul(b,b))
if( i & 1 ) ret = mul(ret, b);
return ret;
}
int f[MAXN + 5][MAXN*MAXN + 5], A[MAXN + 5], n, m;
void solve() {
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++)
scanf("%d", &A[i]);
A[n + 1] = f[0][0] = 1;
for(int i=0;i<=n;i++) {
int t = i*(i + 1)/2;
for(int j=0;j<=t;j++) {
if( f[i][j] ) {
for(int k=i+1;k<=n+1;k++) {
if( A[k] == 1 ) {
f[k][j+(k-i)*(k-i-1)/2] = add(f[k][j+(k-i)*(k-i-1)/2], f[i][j]);
break;
}
else if( A[k] == 2 )
f[k][j+(k-i)*(k-i-1)/2] = sub(f[k][j+(k-i)*(k-i-1)/2], f[i][j]);
}
}
}
}
int ans = 0, t = n*(n + 1)/2;
for(int i=0;i<=t;i++)
ans = add(ans, mul(f[n+1][i], pow_mod(i, m)));
for(int j=0;j<=n+1;j++)
for(int k=0;k<=t;k++)
f[j][k] = 0;
printf("%d\n", ans);
}
int main() {
int T; scanf("%d", &T);
while( T-- ) solve();
}
标签:return,一句,int,2020.03,话题,fa,MAXN,find,MOD 来源: https://www.cnblogs.com/Tiw-Air-OAO/p/12409459.html