题面:

题解:

T1:

算法1:

枚举每个灯塔的方向,并分别判断是否有解。时间复杂度O(K*4^K)。

预计得分:50-70分

算法2:

不难发现,当k≥4的时候一定有解,将最靠左的两个下面的朝右上、上面的朝右下。最右边的两个做同样的处理。不难发现这样一定可以覆盖整个场地。

与算法1结合后可以期望获得100分

# include <bits/stdc++.h>
using namespace std;
namespace Base{
# define mr make_pair
typedef long long ll;
typedef double db;
const int inf = 0x3f3f3f3f, INF = 0x7fffffff;
const ll infll = 0x3f3f3f3f3f3f3f3fll, INFll = 0x7fffffffffffffffll;
template<typename T> void read(T &x){
x = 0; int fh = 1; double num = 1.0; char ch = getchar();
while (!isdigit(ch)){ if (ch == '-') fh = -1; ch = getchar(); }
while (isdigit(ch)){ x = x * 10 + ch - '0'; ch = getchar(); }
if (ch == '.'){
ch = getchar();
while (isdigit(ch)){num /= 10; x = x + num * (ch - '0'); ch = getchar();}
}
x = x * fh;
}
template<typename T> void chmax(T &x, T y){x = x < y ? y : x;}
template<typename T> void chmin(T &x, T y){x = x > y ? y : x;}
}
using namespace Base; const int K = 110;
struct Point{
int x, y;
}p[K], t[K], a[K], b[K];
int k, n, mu[K], flag;
void check(){
int lim = (1 << k);
ll sum = 0;
for (int i = 1; i < lim; i++){
int num = 0;
int ax = 0, ay = 0, bx = n - 1, by = n - 1;
for (int j = 1; j <= k; j++)
if ((i & (1 << (j - 1))) != 0){
num++;
ax = max(a[j].x, ax);
ay = max(a[j].y, ay);
bx = min(b[j].x, bx);
by = min(b[j].y, by);
}
if (ax <= bx && ay <= by)
sum = sum + mu[num] * 1ll * (bx - ax) * (by - ay);
}
if (sum == 1ll * (n - 1) * (n - 1)) flag = true;
} void dfs(int x){
if (x > k){
check();
return;
}
for (int i = 0; i < 4; i++){
a[x].x = min(p[x].x, t[i].x);
a[x].y = min(p[x].y, t[i].y);
b[x].x = max(p[x].x, t[i].x);
b[x].y = max(p[x].y, t[i].y);
dfs(x + 1);
}
}
int main(){
freopen("lighting.in", "r", stdin);
freopen("lighting.out", "w", stdout);
mu[0] = -1;
for (int i = 1; i < K; i++) mu[i] = mu[i - 1] * (-1);
int op; read(op);
while (op--){
read(k); read(n);
for (int i = 1; i <= k; i++)
read(p[i].x), read(p[i].y);
flag = false;
if (k > 4) {
printf("yes\n");
continue;
}
t[0].x = 0, t[0].y = 0;
t[1].x = n - 1, t[1].y = 0;
t[2].x = 0, t[2].y = n - 1;
t[3].x = n - 1, t[3].y = n - 1;
dfs(1);
if (flag == true)
printf("yes\n");
else printf("no\n");
}
return 0;
}

T2:

算法0:

对于如何还原串中的一段,可以用类似线段树查询的方式做,时间复杂度O(N+R-L)。

算法1:

枚举每个玩家的出拳方法。时间复杂度O(3(2N)*(2^N))。

预计得分:20分

算法2:

不难发现,当我们确定最后的获胜者后,我们可以倒推出每一轮比赛的情况。同时我们可以正着推出每一层每个出拳方式的字典序大小关系。所以,当我们确定了最后的情况。我们可以花O(2^N)的时间还原出初始情况。

预计得分:40分

算法3:

其实我们不用还原出整个过程,只要知道底层每种出拳方式有多少个即可。用高精度计算即可。

预计得分:70分(其实取模就可以过了)

算法4:

再次观察后,我们发现。在一层中,每种出拳方式的数量的差不大于1。当我们有差和层数时,我们可以O(1)判断一个状态是否合法。

预计得分:100分

# include <bits/stdc++.h>

namespace Base{
# define mr make_pair
typedef long long ll;
typedef double db;
const int inf = 0x3f3f3f3f, INF = 0x7fffffff;
const ll infll = 0x3f3f3f3f3f3f3f3fll, INFll = 0x7fffffffffffffffll;
template<typename T> void read(T &x){
x = 0; int fh = 1; double num = 1.0; char ch = getchar();
while (!isdigit(ch)){ if (ch == '-') fh = -1; ch = getchar(); }
while (isdigit(ch)){ x = x * 10 + ch - '0'; ch = getchar(); }
if (ch == '.'){
ch = getchar();
while (isdigit(ch)){num /= 10; x = x + num * (ch - '0'); ch = getchar();}
}
x = x * fh;
}
template<typename T> void chmax(T &x, T y){x = x < y ? y : x;}
template<typename T> void chmin(T &x, T y){x = x > y ? y : x;}
}
using namespace Base; const int N = 300010, P = 998244353; struct INT{
int n[N], len;
void GetFromSt(char *st){
len = strlen(st);
for (int i = 0; i < len; i++) n[i] = st[len - i - 1] - '0';
}
}num[4], tmp;
bool operator >=(INT &x, INT &y){
if (x.len > y.len) return true;
if (x.len < y.len) return false;
for (int i = x.len - 1; i >= 0; i--){
if (x.n[i] > y.n[i]) return true;
if (x.n[i] < y.n[i]) return false;
}
return true;
}
INT operator -(INT a, INT &b){
for (int i = 0; i < a.len; i++)
a.n[i] -= b.n[i];
for (int i = 0; i < a.len; i++)
if (a.n[i] < 0) a.n[i] += 10, a.n[i + 1] -= 1;
while (a.len > 0 && a.n[a.len - 1] == 0) a.len--;
return a;
}
int n, op;
const int to[] = {-1, 0, 2, 1, 4, 5, 3, -1};
ll h[N][3], mul[N];
int rk[N][3], tnp[3];
char st[N], mp[3], l[N], r[N];
void error(){
printf("-1\n");
exit(0);
}
void solve(int id, int now, int tag){
if (id == 0){
printf("%c", mp[now]);
return;
}
int nowl = now, nowr = (now + 1) % 3;
if (rk[id - 1][nowl] > rk[id - 1][nowr]) std::swap(nowl, nowr);
if ((tag & 1) != 0){
if (r[id] == '0' && (tag & 2) == 0)
solve(id - 1, nowl, 1);
else solve(id - 1, nowl, 3);
}
else {
if (l[id] == '0'){
if (r[id] == '0' && (tag & 2) == 0)
solve(id - 1, nowl, 0);
else solve(id - 1, nowl, 2);
}
}
if ((tag & 2) != 0){
if (l[id] == '1' && (tag & 1) == 0)
solve(id - 1, nowr, 2);
else solve(id - 1, nowr, 3);
}
else {
if (r[id] == '1'){
if (l[id] == '1' && (tag & 1) == 0)
solve(id - 1, nowr, 0);
else solve(id - 1, nowr, 1);
}
}
}
int main(){
freopen("rsp.in", "r", stdin);
freopen("rsp.out", "w", stdout);
read(n); read(op);
scanf("\n%s", st); num[1].GetFromSt(st);
scanf("\n%s", st); num[2].GetFromSt(st);
scanf("\n%s", st); num[0].GetFromSt(st);
num[3] = num[0]; tmp.len = 1; tmp.n[0] = 2;
if (num[3] >= num[1]) num[3] = num[1];
if (num[3] >= num[2]) num[3] = num[2];
num[0] = num[0] - num[3]; if (num[0] >= tmp) error();
num[1] = num[1] - num[3]; if (num[1] >= tmp) error();
num[2] = num[2] - num[3]; if (num[2] >= tmp) error();
int tag = (num[0].n[0]) + (num[1].n[0] << 1) + (num[2].n[0] << 2);
tag = to[tag];
tag = ((tag - n) % 6 + 6) % 6;
tag = tag / 2;
rk[0][0] = 0, rk[0][1] = 1, rk[0][2] = 2;
h[0][0] = 'P', h[0][1] = 'R', h[0][2] = 'S'; mul[0] = 233;
for (int i = 1; i <= n; i++){
mul[i] = mul[i - 1] * mul[i - 1] % P;
rk[i][0] = std::min(rk[i - 1][0], rk[i - 1][1]) * 3 + std::max(rk[i - 1][0], rk[i - 1][1]);
rk[i][1] = std::min(rk[i - 1][1], rk[i - 1][2]) * 3 + std::max(rk[i - 1][1], rk[i - 1][2]);
rk[i][2] = std::min(rk[i - 1][2], rk[i - 1][0]) * 3 + std::max(rk[i - 1][2], rk[i - 1][0]);
for (int j = 0; j < 3; j++) tnp[j] = (rk[i][j] > rk[i][0]) + (rk[i][j] > rk[i][1]) + (rk[i][j] > rk[i][2]);
for (int j = 0; j < 3; j++){
rk[i][j] = tnp[j];
if (rk[i - 1][j] < rk[i - 1][(j + 1) % 3])
h[i][j] = (h[i - 1][j] + h[i - 1][(j + 1) % 3] * mul[i - 1]) % P;
else h[i][j] = (h[i - 1][(j + 1) % 3] + h[i - 1][j] * mul[i - 1]) % P;
}
}
if (op != 2) printf("%lld\n", h[n][tag]);
if (op == 1) exit(0);
scanf("\n%s", l + 1);
for (int i = 1; i <= n / 2; i++) std::swap(l[i], l[n - i + 1]);
scanf("\n%s", r + 1);
for (int i = 1; i <= n / 2; i++) std::swap(r[i], r[n - i + 1]);
mp[0] = 'P', mp[1] = 'R', mp[2] = 'S';
solve(n, tag, 0);
printf("\n");
return 0;
}

T3:

算法1:

k=1时随便做做,预计得分0-10

算法2:

n≤1000, k≤4,dp统计答案,复杂度O(nvk),

预计得分10。

以下所有多项式的均为卷积(不会啊qaq)。

算法3:

考虑生成函数,以Vi为下标,数量为系数建立多项式f1,那么f1f1就是选两个的方案数。但是这样会有重复,(a,b)与(b,a)会算2次,同时会把(a,a)算进来,那么我们建立多项式f2表示一个物品取两次。那么当k=2时,ans=(f1f1-f2)/2;

预计额外得分20

算法4:

考虑算法3的拓展,记多项式f3为一个物品取三次,那么根据容斥原理,k=3时ans=(f1f1f1-3f2f1+2f3)/6,f2f1表示其中有两个或以上的物品相同,那么在f1f1f1中,一个f2f1会出现三次,即(a,a,b),(a,b,a),(b,a,a),f2f1中也会有f3出现,所以要减去三个f3,但是f1f1f1中本身还有一个f3所以还要减去一个。

预计额外得分30

算分5:

考虑进一步拓展,形式无非就f1f1f1f1,f2f2,f3f1,f2f1f1,f4这几种情况,剩下的问题就是配容斥系数,因为k只有4容斥系数可以手算出来。最终答案是:

Ans=(f1
f1f1f1+8f3f1+3f2f2-6f2f1f1-6f4)/24

预计额外得分40

将算法1,3,4,5拼在一起即可得到满分,时间复杂度O(V log V)

# include <bits/stdc++.h>
# define ll long long
using namespace std; const int T = 100001, N = 600001;
ll ans[N];
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
namespace Transform{
const int P = 998244353, G = 3;
int power(int x, int y){
int i = x; x = 1;
while (y > 0){
if (y % 2 == 1) x = 1ll * i * x % P;
i = 1ll * i * i % P;
y /= 2;
}
return x;
}
void NTT(int *a, int l, int tag){
for (int i = 0, j = 0; i < l; i++){
if (i > j) swap(a[i], a[j]);
for (int k = (l >> 1); (j ^= k) < k; k >>= 1);
}
for (int i = 1; i < l; i <<= 1){
int wn = power(G, (P - 1) / (i * 2));
if (tag == -1) wn = power(wn, P - 2);
for (int j = 0; j < l; j += i + i){
int w = 1;
for (int k = 0; k < i; k++, w = 1ll * w * wn % P){
int x = a[k + j], y = 1ll * w * a[k + j + i] % P;
a[k + j] = (x + y) % P, a[k + j + i] = (x - y + P) % P;
}
}
}
if (tag == -1){
int in = power(l, P - 2);
for (int i = 0; i < l; i++) a[i] = 1ll * a[i] * in % P;
}
}
}
using namespace Transform;
int num1[N], num2[N], num3[N], num4[N], now1[N], now2[N], now3[N], now4[N], len, nn, n, m, k;
void print(){
int sum = 0;
for (int i = 0; i < N; i++)
sum = sum ^ (1ll * ans[i] * i % P);
printf("%d\n", sum);
}
int main(){
freopen("energy.in","r",stdin);
freopen("energy.out","w",stdout);
int inv2 = power(2, P - 2), inv6 = power(6, P - 2), inv24 = power(24, P - 2);
n = read(), k = read();
for (int i = 1; i <= n; i++) num1[read()]++;
for (int i = 1; i <= T; i++) num2[i * 2]= num1[i], num3[i * 3] = num1[i], num4[i * 4] = num1[i];
len = T * 4 + 1;
nn = 1; while (nn < len) nn <<= 1;
if (k == 1){
for (int i = 0; i < nn; i++) ans[i] = num1[i];
print();
return 0;
} if (k == 2){
NTT(num1, nn, 1);
for (int i = 0; i < nn; i++) now1[i] = 1ll * num1[i] * num1[i] % P;
NTT(now1, nn, -1);
for (int i = 0; i < nn; i++) ans[i] = 1ll * (now1[i] - num2[i] + P) * inv2 % P;
print();
return 0;
} if (k == 3){
NTT(num1, nn, 1); NTT(num2, nn, 1);
for (int i = 0; i < nn; i++) now2[i] = 1ll * num2[i] * num1[i] % P;
NTT(now2, nn, -1);
for (int i = 0; i < nn; i++) now1[i] = 1ll * num1[i] * num1[i] % P * num1[i] % P;
NTT(now1, nn, -1);
for (int i = 0; i < nn; i++) ans[i] = (1ll * (now1[i] - 3ll * now2[i] + 2ll * num3[i]) % P * inv6 % P + P) % P;
print();
return 0;
} if (k == 4){
NTT(num1, nn, 1); NTT(num2, nn, 1); NTT(num3, nn, 1);
for (int i = 0; i < nn; i++) now1[i] = 1ll * num1[i] * num1[i] % P * num1[i] % P * num1[i] % P;
NTT(now1, nn, -1);
for (int i = 0; i < nn; i++) now2[i] = 1ll * num3[i] * num1[i] % P;
NTT(now2, nn, -1);
for (int i = 0; i < nn; i++) now3[i] = 1ll * num2[i] * num2[i] % P;
NTT(now3, nn, -1);
for (int i = 0; i < nn; i++) now4[i] = 1ll * num2[i] * num1[i] % P * num1[i] % P;
NTT(now4, nn, -1);
for (int i = 0; i < nn; i++) ans[i] = (1ll * (now1[i] + 8ll * now2[i] + 3ll * now3[i] - 6ll * now4[i] - 6ll *num4[i]) * inv24 % P + P) % P;
print();
return 0;
}
return 0;
}

我觉得这很不提高膜你赛qaq(还是我太菜了)

【题解】JSOIWC2019 Round 5的更多相关文章

  1. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  2. [题解] Codeforces Round #549 (Div. 2) B. Nirvana

    Codeforces Round #549 (Div. 2) B. Nirvana [题目描述] B. Nirvana time limit per test1 second memory limit ...

  3. 题解-CSA Round#18 Randomly Permuted Costs

    Problem CSA Round 18 题意概要:给定一个有重边有自环 \(n\) 点 \(m\) 边的有向无环图(DAG),每条边有其权值,每当你走到一个点 \(x\) 时,所有从 \(x\) 连 ...

  4. [题解]Codeforces Round #709 (Div. 1, based on Technocup 2021 Final Round) - A. Basic Diplomacy

    [题目] A. Basic Diplomacy [描述] Aleksey有n个朋友,有一个m天的假期,每天都需要一个朋友来陪他.给出每天有空的朋友的编号,要求同一个朋友来的天数不能超过m/2上取整.求 ...

  5. 题解——Codeforces Round #508 (Div. 2) T3 (贪心)

    贪心的选取最优解 然后相减好 记得要开long long #include <cstdio> #include <algorithm> #include <cstring ...

  6. 题解——Codeforces Round #508 (Div. 2) T2 (构造)

    按照题意构造集合即可 注意无解情况的判断 #include <cstdio> #include <algorithm> #include <cstring> #in ...

  7. 题解——Codeforces Round #508 (Div. 2) T1 (模拟)

    依照题意暴力模拟即可A掉 #include <cstdio> #include <algorithm> #include <cstring> #include &l ...

  8. 题解——Codeforces Round #507 (based on Olympiad of Metropolises) T2(模拟)

    T2还是模拟 枚举一下第一个放哪里 然后贪心的反转即可 虽然我也不会证,但是这题肯定有解qwq #include <cstdio> #include <algorithm> # ...

  9. 题解——Codeforces Round #507 (based on Olympiad of Metropolises) T1 (模拟)

    暴力模拟即可 就是情况略多 #include <cstdio> #include <algorithm> #include <cstring> using name ...

随机推荐

  1. [WCF] Restful 自定义宿主

    IPersonRetriever: /* * 由SharpDevelop创建. * 用户: Administrator * 日期: 2017/6/2 * 时间: 22:13 * * 要改变这种模板请点 ...

  2. mac上制作ubuntu引导盘

    https://help.ubuntu.com/community/How%20to%20install%20Ubuntu%20on%20MacBook%20using%20USB%20Stick h ...

  3. vue项目实战中的增、删、改、查

    参考:https://blog.csdn.net/xr510002594/article/details/81665762?utm_source=blogxgwz0 https://blog.csdn ...

  4. Win10, VS2017环境下OpenCV3.4.2的配置

    从官网https://opencv.org/releases.html下载OpenCV3.4.2的Win pack进行安装,安装目录便如下图所示: 要能在Visual Studio中使用上述安装的Op ...

  5. Ubuntu 16.04 Java8 安装

    添加ppa apt-get update apt install software-properties-common add-apt-repository ppa:webupd8team/java ...

  6. WPF ComboBox SelectionChanged事件里赋值Text的解决方法

    string sCountry ; private void cbCountry_SelectionChanged(object sender, SelectionChangedEventArgs e ...

  7. PAT1018 Public Bike Management【dfs】【最短路】

    题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024 题意: 给定一个图,一个目的地和每个节 ...

  8. SVN和Git对比梳理

    在日常运维工作中,经常会用到版本控制系统,目前用到最广泛的版本控制器就是SVN和Git,那么这两者之间有什么不同之处呢?SVN(Subversion)是集中式管理的版本控制器,而Git是分布式管理的版 ...

  9. nginx基本用法和HTTPS配置

    nginx作用讲解:1.反向代理:需要多个程序共享80端口的时候就需要用到反向代理,nginx是反向代理的一种实现方式.2.静态资源管理:一般使用nginx做反向代理的同时,应该把静态资源交由ngin ...

  10. cocos2d-x JS 重力感应监听事件

    说明 : 下面监听中的 acc属性 里面有很多可以使用的值 . 添加监听 : cc.inputManager.setAccelerometerEnabled(true); cc.eventManage ...