大佬Alster
水
0 说在前面
看完题就感觉这出题人为造比赛强出题,或者就是从cf上搬来的题。
1 Adore
1.1 问题描述
小 w 偶然间见到了一个 DAG。
这个 DAG 有 m 层,第1层只有1个源点,最后1层只有1个汇点,剩下的每1层都有 k 个节点。
现在⼩ w 每次可以取反第 i(1 < i <
n
−
1
n-1
n−1) 层和第 i + 1 层之间的连边。也就是把原本从(i, k
1
_1
1) 连到 (i + 1, k
2
_2
2) 的边,变成从 (i, k
2
_2
2) 连到 (i + 1,
k
1
k_1
k1)。
请问他有多少种取反的⽅案,把从源点到汇点的路径数变成偶数条?
答案对 998244353 取模。
1.2 输入格式
一行两个整数 m, k。
接下来 m-1 行, 第一行和最后一行有 k 个整数 0 或 1,剩下每行有 k
2
^2
2 个整数 0 或 1,第(j-1) × k + t 个整数表示 (i, j) 到 (i + 1, t) 有没有边。
1.3 输出格式
一行一个整数表示答案。
1.4 样例输入
5 3
1 0 1
0 1 0 1 1 0 0 0 1
0 1 1 1 0 0 0 1 1
0 1 1
1.5 样例输出
4
1.6 数据规模与约定
20% 的数据满⾜ n ≤ 10, k ≤ 2
40% 的数据满⾜ n ≤
1
0
3
10^3
103, k ≤ 2。
60% 的数据满⾜ m ≤
1
0
3
10^3
103, k ≤ 5。
100% 的数据满⾜ 4 ≤ m ≤
1
0
4
10^4
104, k ≤ 10。
1.7 分析咕咕咕,只有吐槽
多谢出题人手下留情。
1.8 代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline void Read(int &p)
{
p=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9')
p=p*10+c-'0',c=getchar();
}
const int MAXN=10234,MAXK=14,MAXS=1044,mod=998244353;
int n,m,a,two[MAXK],f[MAXN][MAXK],g[MAXN][MAXK],dp[MAXN][MAXS];
int main()
{
freopen("adore.in","r",stdin);
freopen("adore.out","w",stdout);
two[0]=1; for(int i=1;i<MAXK;i++) two[i]=two[i-1]*2;
Read(n),Read(m);
for(int i=1;i<=m;i++) Read(a),f[1][1]+=a*two[i-1];
for(int i=2;i<=n-2;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=m;k++)
Read(a),f[i][j]+=a*two[k-1],g[i][k]+=a*two[j-1];
for(int i=1;i<=m;i++) Read(a),f[n-1][i]+=a;
dp[1][1]=1;
for(int i=1;i<=n-1;i++)
for(int j=0,tmp;j<=two[m]-1;j++)
if(dp[i][j])
{
tmp=0; for(int k=1;k<=m;k++) tmp^=f[i][k]*bool(two[k-1]&j);
dp[i+1][tmp]=(1ll*dp[i+1][tmp]+dp[i][j])%mod;
if(i==1 || i==n-1) continue;
tmp=0; for(int k=1;k<=m;k++) tmp^=g[i][k]*bool(two[k-1]&j);
dp[i+1][tmp]=(1ll*dp[i+1][tmp]+dp[i][j])%mod;
}
printf("%d\n",dp[n][0]);
}
2 Confess
2.1 问题描述
小w 隐藏的心绪已经难以再隐藏下去了。
小w 有 n + 1(保证 n 为偶数) 个心绪,每个都包含了 [1, 2n] 的⼀个⼤⼩为 n 的子集。
现在他要找到隐藏的任意两个心绪,使得他们的交小于等于 n2。
2.2 输入格式
一行一个整数 n。
接下来每行一个长度为 k 的字符串,该字符串是一个 64 进制表示,ASCII 码为 x 的字符代表着 x-33,所有字符在 33 到 33 + 63 之间。
转为二进制表示有 6k 位,它的前 2n 个字符就是读入的集合,第 i 位为 1 表示这个集合包含 i,为 0 表示不包含。
2.3 输出格式
一行两个不同的整数表示两个集合的编号。
如果无解输出”NO Solution”。
2.4 样例输入
10
EVK#
IH=#
676"
R7,#
74S"
6V2#
O3J#
S-7$
NU5"
C[$$
3N.#
2.5 样例输出
1 2
2.6 数据规模与约定
对于 20% 的数据满足 n ≤ 100。
对于 50% 的数据满足n ≤ 1 × 10
3
^3
3。
对于 100% 的数据满足 n ≤ 6 × 10
3
^3
3。
2.7 分析咕咕咕,只有吐槽
我佛了。
看到随机化的题我就佛一次。
我佛了。
找alster大佬学了bitset。
2.8 代码
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[6666];
bitset<12006>a[6006];
int n,tmp,len,two[66];
#define lowbit(x) (x&(-(x)))
int main()
{
freopen("confess.in","r",stdin);
freopen("confess.out","w",stdout);
scanf("%d",&n),n++;
two[1]=0,two[2]=1,two[4]=2,two[8]=3,two[16]=4,two[32]=5,two[64]=6;
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
if(!len) len=strlen(s+1),tmp=64-(1<<(6*len-2*n));
s[len]=char(((s[len]-33)&tmp)+33);
for(int j=1,k=0;j<=len;j++)
{
s[j]-=33;
while(s[j]) a[i].set(k+two[lowbit(s[j])]),s[j]-=lowbit(s[j]);
k+=6;
}
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(int((a[i]&a[j]).count())>=(n>>1|1))
return printf("%d %d",i,j),0;
printf("NO Solution");
}
3 Repulsed
3.1 问题描述
小 w 心中的火就要被熄灭了。
简便起见,假设小 w 的内心是一棵 n-1 条边,n 个节点的树。
现在你要在每个节点放一些个灭火器,每个节点可以放任意多个。
接下来每个节点都要被分配给一个至多 k 条边远的灭火器,每个灭火器最多能分配给 s 个节点。
至少要多少个灭火器才能让小 w 彻底死亡呢?
3.2 输入格式
第三个整数 n, s, k。
接下来 n-1 行每行两个整数表示一条边。
3.3 输出格式
一行一个整数表示答案
3.4 样例输入
10 10 3
1 8
2 3
1 5
2 4
1 2
8 9
8 10
5 6
5 7
3.5 样例输出
1
3.6 数据规模与约定
对于 20% 的数据满足 n ≤ 100, k ≤ 2。
对于另外 20% 的数据满足 k = 1。
对于另外 20% 的数据满足 s = 1。
对于 100% 的数据满足 n ≤ 10
5
^5
5, k ≤ 20, s ≤ 10
9
^9
9
3.8 代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline void Read(int &p)
{
p=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9')
p=p*10+c-'0',c=getchar();
}
const int MAXN=102030,MAXM=202030,LOG=22;
int n,s,k,u,v,cnt,ans,ark,vis[MAXN],head[MAXN],to[MAXM],nxt[MAXM],f[MAXN][LOG],g[MAXN][LOG];
inline void addedge(int u,int v){nxt[++cnt]=head[u],head[u]=cnt,to[cnt]=v;}
void dfs(int pos)
{
vis[pos]=1;
for(int i=head[pos];i;i=nxt[i])
if(!vis[to[i]])
{
dfs(to[i]);
for(int j=1;j<=k;j++) f[pos][j]=min(f[pos][j]+f[to[i]][j-1],n),g[pos][j]+=g[to[i]][j-1];
}
g[pos][0]=1;
if(g[pos][k]) ans+=(ark=(g[pos][k]==0?0:(g[pos][k]-1)/s+1)),f[pos][0]=min(1ll*n,1ll*s*ark);
for(int i=0;i<=k;i++) ark=min(f[pos][i],g[pos][k-i]),f[pos][i]-=ark,g[pos][k-i]-=ark;
for(int i=0;i<k;i++) ark=min(f[pos][i],g[pos][k-i-1]),f[pos][i]-=ark,g[pos][k-i-1]-=ark;
}
int main()
{
freopen("repulsed.in","r",stdin);
freopen("repulsed.out","w",stdout);
Read(n),Read(s),Read(k);
for(int i=2;i<=n;i++) Read(u),Read(v),addedge(u,v),addedge(v,u);
dfs(1);
for(int i=k;i>=1;i--)
for(int j=0;i+j<=k;j++)
ark=min(f[1][i],g[1][j]),f[1][i]-=ark,g[1][j]-=ark;
ark=0;
for(int i=0;i<=k;i++) ark+=g[1][i];
ans+=(ark==0?0:(ark-1)/s+1);
printf("%d\n",ans);
}
4 说在后面
咋感觉自己像个营销号或者爬虫号一样呢?
hub.io/flowchart.js/