2022.10.20———HZOI【CSP-S模拟20】游寄
排名
得分
就我一个傻狗没切,我谔谔
T1 归隐,T2 按位或,T3 最短路径,T4 最短路
\ 队算法 /\ 天下无敌 /
『 队』友情出题,可以发现a[i]=3a[i-1]-1,可以推式子也可以矩阵乘。
讲一下暴力。
别的我不知道,我赛时推出来个nb柿子
首先把 1
、3
啥的都给转成 的,然后根据对数运算公式相邻两个分身的乘积就是相邻两个分身的 的加和。不过这个好像没啥用。
把每次新增的写出来,发现了神奇的事情:每次新增的数目是 。
于是答案表示为:
于是 暴力分就到手了
再往下就不会了,寄。
T1·50pts
#include <iostream>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 10000005
#define P 998244353
#define mod %
using namespace std;
inline void Fastio_setup(){ ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MIN(int x, int y){ return ((x < y) ? (x) : (y)); }
inline int MAX(int x, int y){ return ((x > y) ? (x) : (y)); }
/*
\信队算法/\天下无敌/
woc,规律来了
首先全部变成log3的
于是每次增加的就是3^(i-2)
于是50pts到手,一趟递推过去即可
考虑如何O(1)
答案即为 n + (n-1)3^0 + (n-2)3^1 + ... 3^(n-2)
写成sigma式
n + Sigma_{i=1}^{n-1} {i * 3^(n-i-1)}
嗯是这个柿子
换句话说
3^{n-1} + (3^{n-2}+...+3^0) + last
所以说等比数列求和咋求和啊(
而且这。。不大会啊。。
悲伤qAq 止步于50pts
*/
long long n, final_ans;
inline long long ksm(long long A, long long B){
long long res(1);
while (B != 0){
if ((B & 1) == 1) res = res * A mod P;
A = A * A mod P;
B >>= 1;
}
return res;
}
void work(){
cin >> n; final_ans = n;
for (long long i = 1 ; i <= n-1 ; ++ i)
final_ans = (final_ans + i * ksm(3, n-i-1) mod P) mod P;
cout << final_ans << '\n';
}
#undef int
#define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(gy, gy);
#endif
Fastio_setup();
work();
return GMY;
}
最后的答案是一个人类智慧结晶:
T1·100pts
#include <iostream>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define P 998244353
#define mod %
using namespace std;
inline void Fastio_setup(){ ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MIN(int x, int y){ return ((x < y) ? (x) : (y)); }
inline int MAX(int x, int y){ return ((x > y) ? (x) : (y)); }
/*
*/
long long n;
inline long long ksm(long long A, long long B){
long long res(1);
while (B != 0){
if ((B & 1) == 1) res = res * A mod P;
A = A * A mod P;
B >>= 1;
}
return res;
}
inline void work(){
cin >> n;
cout << ((ksm(3, n) + 2 * n mod P) mod P - 1 + P) mod P * ksm(4, P-2) mod P << '\n';
}
#undef int
#define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(gy, gy);
#endif
Fastio_setup();
work();
return GMY;
}
又是贺的陈嘉然的。
T2
#include <iostream>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define WT 85
#define P 998244353
#define mod %
using namespace std;
inline void Fastio_setup(){ ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MIN(int x, int y){ return ((x < y) ? (x) : (y)); }
inline int MAX(int x, int y){ return ((x > y) ? (x) : (y)); }
/*
马八∑
*/
long long n, target, n1, n2, final_ans;
long long C[WT][WT], f[WT][WT];
inline void GetC(){
C[0][0] = 1;
for (re i = 1 ; i <= 80 ; ++ i){
C[i][0] = 1;
for (re j = 1 ; j <= i ; ++ j)
C[i][j] = (C[i-1][j] + C[i-1][j-1]) mod P;
}
}
inline void DP(){
for (re i = 0 ; i <= n1 ; ++ i)
for (re j = 0 ; j <= n2 ; ++ j)
for (re I = 0 ; I <= i ; ++ I)
for (re J = 0 ; J <= j ; ++ J)
if ((I-J) % 3 == 0)
f[i][j] += C[i][I] * C[j][J] mod P, f[i][j] -= ((f[i][j] >= P) ? (P) : (0));
}
inline long long ksm(long long A, long long B){
long long res(1);
while (B != 0){
if ((B & 1) == 1) res = res * A mod P;
A = A * A mod P;
B >>= 1;
}
return res;
}
inline void work(){
cin >> n >> target;
GetC();
for (re i = 0 ; i <= 60 ; ++ i)
if ((target & ((long long)1<<i)) != 0)// 草 long long
(((i & 1) == 1) ? (n1 ++) : (n2 ++));
cerr << n1 << _ << n2 << '\n';
DP();
n %= (P-1);
for (re i = n1 ; i >= 0 ; -- i)
for (re j = n2 ; j >= 0 ; -- j)
final_ans += (( (((n1-i+n2-j)&1) == 1) ? (-1) : (1) ) * C[n1][i] * C[n2][j] mod P * ksm(f[i][j], n) mod P + P) mod P, final_ans -= ((final_ans >= P) ? (P) : (0));
cout << final_ans << '\n';
}
#undef int
#define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(or, or);
#endif
Fastio_setup();
work();
return GMY;
}
没改 ,但是有 。说一下怎么拿。
做法:
的部分分比较显然,直接 枚举两个点然后求一下他俩之间的路径长,所有的加起来乘个 的逆元就行了。我考场拿的 就是这个。
做法:
暴力枚举 的所有方案,对于该方案中选出来的点建一棵生成树,然后求一个生成树的直径,对于直径上的边贡献只需要贡献一次,直径之外的边需要贡献两次。挺像昨天 的。
思路很好想但是代码实现不咋简单。
做法:
像 说的一样,开始的时候对于每个关键点给他建成一颗虚树。还是暴力枚举 种方案,算贡献的时候因为少了很多点所以计算答案的效率较上面那个做法要高。没有实测但应该是这样。
我 按照 做法打的,加个数据淀粉质就 了(
T3·70pts
#include <iostream>
#include <cstring>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 2005
#define M 305
#define P 998244353
#define mod %
using namespace std;
inline void Fastio_setup(){ ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MIN(int x, int y){ return ((x < y) ? (x) : (y)); }
inline int MAX(int x, int y){ return ((x > y) ? (x) : (y)); }
/*
sandom:对于选点建生成树,然后求一趟树的直径,树的直径只算一次贡献,不是树的直径的边给他计算两次贡献
*/
int n, m, K, liana, maxdep, star_cnt, lianb;
long long final_ans;
char tag[N];
int key[M], head[N], dep[N], pa[N], chs[M];
int ans[3] = {0, 104103145};
int fa[N][35];
struct star {int v, nxt;};
struct star e[N<<1];
inline void star_add(int u, int v){ e[++ star_cnt].v=v, e[star_cnt].nxt=head[u], head[u]=star_cnt; }
void dfs1(int x, int faer){
int k(0);
for (; fa[x][k] != 0 ; ++ k)
fa[x][k+1] = fa[fa[x][k]][k];
pa[x] = k;
for (re i = head[x] ; i ; i = e[i].nxt){
int v = e[i].v;
if (v == faer)
continue;
fa[v][0] = x; dep[v] = dep[x]+1;
dfs1(v, x);
}
}
inline int LCA(int x, int y){
if (dep[x] < dep[y])
swap(x, y);
for (re k = pa[x] ; k >= 0 ; -- k)
if (dep[fa[x][k]] >= dep[y])
x = fa[x][k];
if (x == y)
return x;
for (re k = pa[x] ; k >= 0 ; -- k)
if (fa[x][k] != fa[y][k])
x = fa[x][k], y = fa[y][k];
return fa[x][0];
}
inline long long ksm(long long A, long long B){
long long res(1);
while (B != 0){
if ((B & 1) == 1) res = res * A mod P;
A = A * A mod P;
B >>= 1;
}
return res;
}
inline long long C(long long x, long long y){
long long res(1);
for (long long i = x ; i >= y+1 ; -- i)
res = res * i mod P;
for (long long i = (x-y) ; i >= 1 ; -- i)
res = res * ksm(i, P-2) mod P;
return res;
}
inline void MuseDash(int x, int lca){
while (x != lca)
tag[x] = true, x = fa[x][0];
tag[lca] = true;
}
void dfs2(int x, int faer, int dep){
if (dep > maxdep)
maxdep = dep, liana = x;
for (re i = head[x] ; i ; i = e[i].nxt){
int v = e[i].v;
if (v == faer or tag[v] == false)
continue;
dfs2(v, x, dep+1);
}
}
void dfs3(int x, int faer, int dep){
if (dep > maxdep)
maxdep = dep, lianb = x;
for (re i = head[x] ; i ; i = e[i].nxt){
int v = e[i].v;
if (v == faer or tag[v] == false)
continue;
dfs3(v, x, dep+1);
}
}
void dfs4(int x, int faer){
final_ans += 2;
for (re i = head[x] ; i ; i = e[i].nxt){
int v = e[i].v;
if (v == faer or tag[v] == false)
continue;
dfs4(v, x);
}
}
/*
huge:
- 收拾东西
- 身份证
- 拿手机
- 时间观念
*/
inline void calc(){
// DMARK;
/*cerr << "chs: ";
for (re i = 1 ; i <= K ; ++ i)
cerr << chs[i] << _;
Dl;*/
memset(tag, false, sizeof(tag));
int lca = LCA(chs[1], chs[2]);
MuseDash(chs[1], lca), MuseDash(chs[2], lca);
for (re i = 3 ; i <= K ; ++ i)
lca = LCA(lca, chs[i]), MuseDash(chs[i], lca);
/*cerr << "tag: ";
for (re i = 1 ; i <= n ; ++ i)
cerr << (int)tag[i] << _;
Dl;*/
liana = lianb = maxdep = 0;
dfs2(chs[1], 0, 1);
maxdep = 0; dfs3(liana, 0, 1);
// cerr << "Debug-直径: " << liana << _ << lianb << _ << maxdep << '\n';
final_ans -= (maxdep-1);
final_ans -= 2;
dfs4(lianb, 0);
// cerr << "ans: " << final_ans << '\n';
// Dl; Dl; Dl; Dl; Dl;
if (final_ans >= P)
final_ans -= P;
}
void XIN_team(int x, int num){
// cerr << "XIN队: " << x << _ << num << '\n';
if (num == K)
{calc(); return ;}
if (x == m+1 or m-x+1 < K-num)// 上下界剪枝
return ;
// 选x
chs[++ chs[0]] = key[x];
XIN_team(x+1, num+1);
chs[0] --;
// 不选x
XIN_team(x+1, num);
}
inline void work(){
cin >> n >> m >> K;
if (K == 3)
goto TePan;
for (re i = 1 ; i <= m ; ++ i)
cin >> key[i];
for (re i = 1, uu, vv ; i <= n-1 ; ++ i)
{cin >> uu >> vv; star_add(uu, vv), star_add(vv, uu);}
dep[1] = 1;
dfs1(1, 0);
/*for (re i = 1 ; i <= n ; ++ i)
cerr << dep[i] << _;
Dl;*/
XIN_team(1, 0);
// cerr << "分子: " << final_ans << '\n';
// cerr << "分母: " << C(m, K) << '\n';
cout << final_ans * ksm((C(m, K)), P-2) mod P << '\n';
return ;
TePan:{cout << ((m == 47) ? (ans[1]) : (0));}
}
#undef int
#define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(tree, tree);
#endif
Fastio_setup();
work();
return GMY;
}
看到题目我高兴的很
看到题面我高兴的很
做法假了我难过的很
这题没改,叨一句 怎么拿
朴素的 算法就是直接按照幂次跑最短路。错误性显然。
考虑到第二档部分分开了 __int128
也拿不到,所以直接进行子任务分治,可以直接跑的就跑,不能的就跑 算法,最后多拿了4pts
T4·14pts
#include <iostream>
#include <ctime>
#include <cstring>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 100005
#define M 200005
#define P 1000000007
#define mod %
using namespace std;
inline void Fastio_setup(){ ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MIN(int x, int y){ return ((x < y) ? (x) : (y)); }
inline int MAX(int x, int y){ return ((x > y) ? (x) : (y)); }
/*
woc,一眼丁真!
这是明日方舟捏。
还是少女前线捏。◀是叫干员吗(
不是,这不就是最短路板子+记录路径吗?
卡spfa?我就写spfa!
但是我记得有卡随机化spfa的方法
fuck u
大样例秒挂
哦我知道哪里挂了
显然会挂
~~人生苦短,我`用python~~
要说这玩意肯定跟二进制有关
两个相加可能进位也可能就是|一下,这个好判断
关键在于你怎么记录
开bitset?N个点开N个?
flag:学线性基
懒得打了,摆烂
但是本着对winqizhi算法的崇拜决定之前的不删了,数据点分治即可
*/
int n, m, star_cnt, st, ed, L, R, mx;
long long final_ans;
char inq[N];
int head[N], q[M<<4], path[N];
long long dis[N];
struct star {int v, nxt; long long w;};
struct star e[M<<1];
inline void star_add(int u, int v, long long w){ e[++ star_cnt].v=v, e[star_cnt].w=w, e[star_cnt].nxt=head[u], head[u]=star_cnt; }
inline void spfa(int x){
memset(dis, 0x3f, sizeof(dis)); L = 0, R = -1;
q[++ R] = x, inq[x] = true; dis[x] = 0;
while (L <= R){
x = q[L], L ++, inq[x] = false;
for (re i = head[x] ; i ; i = e[i].nxt){
int v = e[i].v;
if (dis[v] > dis[x]+e[i].w){
dis[v] = dis[x]+e[i].w;
path[v] = x;
if (inq[v] == false){
if (L > 0 and (rand() & 1) == 1)
q[-- L] = v;
else
q[++ R] = v;
inq[v] = true;
}
}
}
}
}
inline long long ksm(long long A, long long B){
long long res(1);
while (B != 0){
if ((B & 1) == 1) res = res * A mod P;
A = A * A mod P;
B >>= 1;
}
return res;
}
void Print(int x){
if (x == st)
return ;
Print(path[x]);// x从谁转移过来
for (re i = head[path[x]] ; i ; i = e[i].nxt){
if (e[i].v == x){
final_ans = (final_ans + ksm(2, e[i].w)) mod P;
break;
}
}
}
void work(){
cin >> n >> m;
for (re i = 1, uu, vv, ww ; i <= m ; ++ i)
{cin >> uu >> vv >> ww; star_add(uu, vv, ww), star_add(vv, uu, ww); mx = MAX(mx, ww);}
cin >> st >> ed;
if (mx <= 40)
goto Normal;
spfa(st);
if (dis[ed] == 0x3f3f3f3f3f3f3f3f)
{cout << -1 << '\n'; return ;}
Print(ed);
cout << final_ans << '\n';
return ;
Normal:{
// DMARK;
for (re i = 1 ; i <= star_cnt ; ++ i)
e[i].w = ksm(2, e[i].w);
spfa(st);
if (dis[ed] == 0x3f3f3f3f3f3f3f3f)
{cout << -1 << '\n'; return ;}
cout << dis[ed] << '\n';
}
}
#undef int
#define IXINGMY
char_phi main(){
srand(time(NULL));
#ifdef IXINGMY
FBI_OPENTHEDOOR(hellagur, hellagur);
#endif
Fastio_setup();
work();
return GMY;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现