A : 模拟
B : 打表
C : 容斥+反演+推式子
D : Unfinished
E : Unfinished
这些题是赛后刷的,因为当时并不知道有这场比赛,就算知道可能也因为网络或者时间问题打不了吧…
D和E看起来没什么人过,估计很难,先丢了。
A. Convert to Ones
考虑一个串,连续的0有多少段,显然一次取反操作最多使段数减一,一次翻转也至多使段数减一。那就挑取反和翻转中代价小的一直做就好了。注意最后只剩1个连续的0段的时候只能取反。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define cmax(_i,_j) ((_i)<(_j)?(_i)=(_j):0)
#define cmin(_i,_j) ((_i)>(_j)?(_i)=(_j):0)
#define N 300005
using namespace std;
namespace runzhe2000
{
int n, x, y;
char s[N];
void main()
{
scanf("%d%d%d%s",&n,&x,&y,s+1); int cnt = 0;
for(int i = 1; i <= n; i++) if(s[i] == '0' && s[i-1] != '0') cnt++;
if(!cnt){printf("0\n");return;}
if(x >= y) printf("%I64d\n",1ll*y*cnt);
else printf("%I64d\n",1ll*x*(cnt-1)+y);
}
}
int main()
{
runzhe2000::main();
}
B. Roman Digits
这题我不是太清楚怎么做…总之打表打出来发现从n=11开始,答案是一个公差为49的等差数列。啊不会证。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define cmax(_i,_j) ((_i)<(_j)?(_i)=(_j):0)
#define cmin(_i,_j) ((_i)>(_j)?(_i)=(_j):0)
using namespace std;
namespace runzhe2000
{
int f[12]={0, 4, 10, 20, 35, 56, 83, 116, 155, 198, 244, 292};
void main()
{
int n; scanf("%d",&n);
if(n <= 11) printf("%d\n",f[n]);
else printf("%I64d\n",f[11]+(n-11)*49ll);
}
}
int main()
{
runzhe2000::main();
}
C. Sky Full of Stars
首先想法肯定是容斥。设 f[i][j] f [ i ] [ j ] 表示至少有 i i 行, 列颜色一样的方案数。设 g[i][j] g [ i ] [ j ] 表示恰有 i i 行, 列颜色一样的方案数。
然后它们会有这样的关系 :
对这个东西用类似二项式反演的东西可以推(猜)出(测)出它的反演应该是这样的:
如果不太确定,可以打个表发现上面这个式子是对的,然后我们要求出所有的 g g ,至少就会是平方级别的,实际上只要求 ,然后拿 3n2 3 n 2 减一下就好了。那么我们现在只要求一个东西啦。
其中
f[i][j]=3(n−i)(n−j)+1(ni)(nj)
f
[
i
]
[
j
]
=
3
(
n
−
i
)
(
n
−
j
)
+
1
(
n
i
)
(
n
j
)
,若
i,j
i
,
j
都不为
0
0
,若
i
i
为 ,
j
j
不为。对称的
i
i
不为,
j
j
为类似。
f[i][j]=3n2
f
[
i
]
[
j
]
=
3
n
2
,若
i,j
i
,
j
都为
0
0
后两种情况分别能在, O(1) O ( 1 ) 时间内做完,考虑第一种,也就是
然后就OK了。
#include<bits/stdc++.h>
#define N 1000005
#define MOD 998244353
using namespace std;
typedef long long ll;
int fac[N], inv[N];
int comb(int a, int b){return 1ll*fac[a]*inv[b]%MOD*inv[a-b]%MOD;}
int fpow(int a, ll b)
{
int r = 1;
for(;b;b>>=1)
{
if(b&1)r=1ll*r*a%MOD;
a=1ll*a*a%MOD;
}
return r;
}
int main()
{
int n; scanf("%d",&n);
fac[0] = 1; for(int i = 1; i <= n; i++) fac[i] = 1ll * fac[i-1] * i % MOD;
inv[1] = 1; for(int i = 2; i <= n; i++) inv[i] = 1ll*(MOD-MOD/i)*inv[MOD%i]%MOD;
inv[0] = 1; for(int i = 1; i <= n; i++) inv[i] = 1ll*inv[i-1]*inv[i]%MOD;
int ans = 0;
ans += fpow(3,1ll*n*n); // f 0 0
for(int i = 1; i <= n; i++) // f 0 x
(ans += (i%2?MOD-1ll:1ll) * fpow(3,i) % MOD * fpow(3,1ll*(n-i)*n) % MOD * comb(n, i) % MOD * 2 % MOD) %= MOD;
for(int i = 1; i <= n; i++) // f x x
(ans += 3ll * comb(n,i) % MOD * (i%2?MOD-1:1) % MOD * (fpow(fpow(3,n-i)-1, n) - fpow(3, 1ll*n*(n-i)) + MOD) % MOD) %= MOD;
printf("%d\n",(fpow(3,1ll*n*n)-ans+MOD)%MOD);
}