确实,今天仍然是数学,仍然是心态爆炸,虽然通过了一番痛苦的思考把第二题给切了然后顺手拿了个机房第一(当然是因为其他大佬都爆掉了,不然也轮不到我)。

T1 数列 Sequence

题目描述

我们称一个长度为 2n 的数列是有趣的,当且仅当该数列满足以下三个条件:

(1)它是从 1 到 2n 共 2n个整数的一个排列{ai};

(2)所有的奇数项满足 a1<a3<…<a2n-1,所有的偶数项满足 a2<a4<…<a2n;

(3)任意相邻的两项 a2i-1与 a2i(1≤i≤n)满足奇数项小于偶数项,即:a2i-1<a2i。  现在的任务是:对于给定的n,请求出有多少个不同的长度为 2n 的有趣的数列。因为 最后的答案可能很大,所以只要求输出答案 mod P 的值。

输入格式

输入文件只包含用空格隔开的两个整数 n 和 P。

输出格式

仅含一个整数,表示不同的长度为 2n 的有趣的数列个数 mod P 的值。

样例输入

3 6

样例输出

5

数据范围与约定

对于 30%的数据满足 n≤1000;

对于另外 30%的数据满足 P 为质数;

对于100%的数据满足 n≤1000000 且 P≤1000000000。

洛谷题号P3200

分析

对于这道题,我们打表之后,我们不难发现,这是一道标标准准的Catalan数列。

我们可以单独看奇数和偶数相,我们可以把它看作是两个队列,按照1~n的顺序填入两个队列中,其中奇数项队列的长度不能超过偶数项长度,否则就会导致我们要求的序列出现偶数项小于它前面的奇数项的情况。这个过程我们可以形象地看成是再偶数项填为进栈,填奇数项为出栈,保证有东西可以出栈。于是乎就很显而易见的可以看出这是Catalan数列了。

那么怎么求呢?

由于这里并不保证 P 是质数,所以我们不能使用求逆元的方法来求组合数。因此我们选用拆分质因子约分的方式来求解组合数。也就是对于式子我们对 n! , m!, (n - m)! 分别进行质因数分解然后约分。

同样的道理,由于不保证 p 是质数,因而我们不能使用这个公式来求取卡特兰数,我们转而使用来求解,至于证明吗你只需要把这两个数用阶乘的方式表示出来合并就可以了。

代码

又是我丑陋的代码

#include<bits/stdc++.h>using namespace std;const int MAXN = 2e7 + 5;int inpt()
{int x = 0, f = 1;char ch;for(ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar());if(ch == '-'){f = -1;ch = getchar();}do{x = (x << 3) + (x << 1) + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');return f * x;
}int n, p;int v[MAXN], pri[MAXN], tot = 0;
void EuPri()
{memset(v, 0, sizeof(v));for(int i = 2; i <= MAXN - 5; i++){if(v[i] == 0){v[i] = i;pri[++tot] = i;}for(int j = 1; j <= tot && i * pri[j] <= MAXN - 5 && pri[j] <= v[i]; j++){v[i * pri[j]] = pri[j];}}
}int QPow(int x, int y)
{int val = 1;while(y){if(y & 1){val = 1ll * val * x % p;}x = 1ll * x * x % p;y >>= 1;}return val;
}int calc(int N, int k)//计算某个质因子的数量,原理可以翻阅lyd的书
{long long val = 0, kk = k;//记得一定要开long long,别问我怎么知道的while(kk <= N){val += N / kk;kk *= k;}return val;
}int C(int M, int N)//组合数
{int val = 1;for(int i = 1; i <= tot && pri[i] <= N; i++){
//      printf("%d\n",i);//看着诡异的调试语句你就知道这个死循环我调的多痛苦了
//      if(i == 6542){
//          int t = 0;
//      }int x = calc(N, pri[i]), y = calc(M, pri[i]), z = calc(N - M, pri[i]);int res = x - y - z;//约分val = 1ll * val * QPow(pri[i], res) % p; }return val;
}int main()
{freopen("sequence.in", "r", stdin);freopen("sequence.out", "w", stdout);n = inpt(), p = inpt();EuPri();int x = C(n, 2 * n), y = C(n - 1, 2 * n);//计算非质数的Catalan数 printf("%d", ((x - y) % p + p) % p);fclose(stdin);fclose(stdout);return 0;
}

T2 乘法 Mul

题目描述

输入一个 n ∗ n 的矩阵 A,请求出对 m 取模的结果。

输入格式

第一行为三个正整数 n, k, m,含义如上所述;

接下来 n 行,每行输入 n 个非负整数,用于描述矩阵 A。

输出格式

输出 n 行,每行 n 个整数,表示答案矩阵。

样例输入

2 2 5

2 1

0 3

样例输出

1 1

0 2

数据范围与约定

对于前 30% 的数据,k<=30;

对于另外 30% 的数据,n=1;

对于 100%的数据,n<=30, k<=1e9 , m<=1e4,输入矩阵的数在 0~m-1 范围内

解法一:

分析

这道题也是我考场上唯一做出来的题,花了一个小时构思,一个半小时编码,剩下半个小时摆烂,我现在只想摊着。

简单讲一下我的思路,通过高一数学课我们可以知道,在等差数列中(记公差为 q ,前n项和为), 也成等比数列且公比为。于是我们可以把这一点运用到这道题上。

观察下列式子

我们可以用一个数组 sum 来储存前项的和,表示。再用一个数组来储存,这样我们就可以求出整的2的次方项数的和了。

那么剩下的不是整的2的次方数和怎么办呢?

我们可以类比于快速幂的思想,将后几项拆分成长度为  的几段也就是下面这样(用截图做的图片,有个水印懒得取了,将就看一下把):

细心的小伙伴发现了,我们分成的小区段只需要乘上他开头的(假设为)前一个次方就可以了,至于怎么分区段嘛,类比快速幂就行了。

代码

献上我丑陋的代码

#include<bits/stdc++.h>
using namespace std;const int MAXN = 35;
const int LOG = 31;int inpt()
{int x = 0, f = 1;char ch;for(ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar());if(ch == '-'){f = -1;ch = getchar();}do{x = (x << 3) + (x << 1) + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');return f * x;
}int n, k, p;//p是原题中的m struct Matrix{int mat[MAXN][MAXN];int l, h;Matrix operator *(Matrix qwq)const{Matrix val;memset(val.mat, 0, sizeof(val.mat));val.l = qwq.l;val.h = h;if(l == qwq.h){for(int i = 1; i <= h; i++){for(int j = 1; j <= qwq.l; j++){int res = 0;for(int k = 1; k <= l; k++){res = (res + (1ll * mat[i][k] * qwq.mat[k][j]) % p) % p;}val.mat[i][j] = res;}}return val;}}Matrix operator %(int qwq)const{Matrix val;memset(val.mat, 0, sizeof(val.mat));val.l = l;val.h = h;for(int i = 1; i <= l; i++){for(int j = 1; j <= h; j++){val.mat[i][j] = mat[i][j] % qwq;}}return val;}Matrix operator +(Matrix qwq)const{Matrix val;memset(val.mat, 0, sizeof(val.mat));val.l = l;val.h = h;if(l == qwq.l && h == qwq.h){for(int i = 1; i <= l; i++){for(int j = 1; j <= h; j++){val.mat[i][j] = (mat[i][j] + qwq.mat[i][j]) % p;}}return val;}}
}a, ans, sum[35], pw[35];long long pw2[35];void init()
{pw2[0] = 1;for(int i = 1; i <= LOG; i++){pw2[i] = pw2[i - 1] * 2;//初始化2的次方}n = inpt(), k = inpt(), p = inpt();a.l = n;a.h = n;for(int i = 1; i <= n; i++){for(int j = 1; j <= n; j++){a.mat[i][j] = inpt();}}
}int main()
{
//  freopen("data.out", "r", stdin);freopen("mul.in", "r", stdin);freopen("mul.out", "w", stdout);init();int cnt = 0;pw[0] = sum[0] = a;while(pw2[cnt] <= k){pw[++cnt] = pw[cnt - 1] * pw[cnt - 1] % p;//初始化A的次方及次方和sum[cnt] = (sum[cnt - 1] + (sum[cnt - 1] * pw[cnt - 1]) % p) % p;}cnt--;ans = sum[cnt];int del = k - pw2[cnt];int nw = pw2[cnt] + 1;while(del){//处理剩下的部分int x = upper_bound(pw2, pw2 + cnt, del) - pw2 - 1;//分成小块
//      int y = upper_bound(pw2,    //这个是错的别被误导    pw2 + 32, nw) - pw2 - 1;int y = nw - 1;//A^i-1Matrix qwq = sum[x];int z = 0;while(y){if(y & 1){qwq = qwq * pw[z] % p;}z++;y >>= 1;}ans = (ans + qwq) % p;del -= pw2[x];nw += pw2[x];}for(int i = 1; i <= n; i++){for(int j = 1; j <= n; j++){printf("%d ", ans.mat[i][j]);}puts("");}fclose(stdin);fclose(stdout);return 0;
}
/*
2 2 5
2 1
0 32 2 30
2 1
0 33 7 17
2 1 4
3 1 0
7 4 22 1000000000 1027
2 1
0 3*/

我这份代码是我考场上做的,xyh巨佬为我们提供了一份更加简洁的代码,详情可见他的博客(他暂时还没写,等他写了我会换链接的)。

解法二

我不想分析了

这个方法我还没来得及仔细看,这里把yyr学长的题解粘过来(我不知道他的博客链接,也不知道他发过没有TAT)

代码

这个方法的代码我也没来得及打,这里贴上杰哥的博客链接他也暂时还没写博客,等他写了我再换链接。

T3 生物 Creature

题目描述

在一个无限长的一维空间中,存在着一个奇特的生物,它的身体上顺次有着 n + 1 个 刻印,每个刻印可以用一个正整数来表示。已知它最后一个刻印的值为 m,而其它 n 个刻 印的值均不超过 m,并且两个刻印的值可以相同。 这个生物每次可以选中它的任意一个刻印,并且按照这个刻印的值 k,选择向它所在位 置的前或后闪烁 k 个单位。我们称可以使得这个生物能够通过若干次闪烁,到达一维空间 任何一个位置的刻印序列为超刻印序列。 现在刻印序列显然一共有 种,为了研究这个生物,请你求出其中超刻印序列的数 目。

输入格式

仅一行两个整数,分别为 n, m。

输出格式

输出一行一个整数,表示超刻印序列的数目对 1e9 +7 取模的结果。

样例输入

2 4

样例输出

12

数据范围与约定

对于前 20%的数据,保证 n,m <= 5;

对于 100%的数据,保证 1<=n<=15,1<=m<=1e8。

分析

因为他要求再这个 m 结尾的数列任意组合后可以到达该空间内任意一个点,所以我们可以知道,只要这个数列中的数通过任意倍数的组合可以组成 1 就可以了,通过裴蜀定理我们可以知道,满足这个条件只需要保证这n个数的 gcd 为 1 就可以了。因为直接处理 n 个数的 gcd 不好处理,于是我们选择正难则反,只需要再所有排列情况减去 的情况即可。

由于我们知道这个数列中一定有数字 m 的存在,所以只要则说明前面的数中包含 m 的质因子的组合产生的数。也就是(假设 m 的质因子为的大小(A表示满足该条件的序列),而这个并集的大小也是十分难以求得的,于是我们反而求出的大小也就是 的大小,运用容斥原理求得即可。而再 时,每个数的不同的质因子数目不会超过10个(最小的10个质数相乘已经超过了2e9)(而且指数之和不会超过31()虽然这道题用不到)。所以我们运用dfs计算容斥复杂度时完全符合的。

代码

献上我丑陋的代码

#include<bits/stdc++.h>
using namespace std;const int MAXN = 1e4 + 5;
const int MOD = 1e9 + 7;int inpt()
{int x = 0, f = 1;char ch;for(ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar());if(ch == '-'){f = -1;ch = getchar();}do{x = (x << 3) + (x << 1) + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');return f * x;
}int n, m;int v[MAXN], pri[MAXN], tot = 0;
void EuPri()
{memset(v, 0, sizeof(v));for(int i = 2; i <= MAXN - 5; i++){if(v[i] == 0){v[i] = i;pri[++tot] = i;}for(int j = 1; j <= tot && i * pri[j] <= MAXN - 5 && pri[j] <= v[i]; j++){v[i * pri[j]] = pri[j];}}
}int p[MAXN], cnt = 0;
void Divide(int x)//质因数分解
{for(int i = 1; i <= tot && pri[i] <= x; i++){if(x % pri[i] == 0){p[++cnt] = pri[i];while(x % pri[i] == 0){x /= pri[i];}}}if(x != 1){p[++cnt] = x;}
}int QPow(int x, int y)
{int val = 1;while(y){if(y & 1){val = 1ll * val * x % MOD;}x = 1ll * x * x % MOD;y >>= 1;}return val;
}int s[30], ans = 0;//s储存当前情况下的质因子组合
void dfs(int Num, int Lst, int Lim, int op)//求解容斥原理
{//Num表示当前已经用了多少个质因子,Lst表示上一个用的质因子是谁
//Lim表示当前最多可以使用多少个质因子,op表示当前计算的符号if(Num >= Lim){int val = 1;for(int i = 1; i <= Num; i++){val *= s[i];}ans = ((ans + (QPow(m / val, n) * op) )% MOD + MOD) % MOD;//n个位置放m/val个数return ;}for(int i = Lst + 1; i <= cnt; i++){s[Num + 1] = p[i];dfs(Num + 1, i, Lim, op);}
}int main()
{freopen("creature.in", "r", stdin);freopen("creature.out", "w", stdout);n = inpt(), m = inpt();EuPri();Divide(m);for(int i = 1, op = 1; i <= cnt; i++, op *= -1){dfs(0, 0, i, op);}printf("%d", ((QPow(m, n) - ans) % MOD + MOD) % MOD);//记得一定要减fclose(stdin);fclose(stdout);return 0;
}

充实而精彩的五一三天集训终于是结束了,接下来的时间就是疯狂的补作业了,但我现在只想摊着。。。

2022.5.2 五一假期痛苦的第三天相关推荐

  1. 2022.4.30 五一假期快乐的第一天

    今天早上学校停电被迫放假半天,当时我可开心伤心坏了. 对,没错,下午又开始考试... 这大概又是哪一届学长考过的题? T1 Pilot 题目描述 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞 ...

  2. 五一假期出行必备的高科技手册

    今天小编看了眼朋友圈,发现无节操的同学真是太多了,你们出去玩就好了,为啥要发图呢--各种晒,简直要虐死上班狗啊. 不过掐指一算,小编期盼已久的五一马上就要来了.抱着拯救同样期待假期出行同胞们的想法,小 ...

  3. “五一”假期出行,伴随着哪些风险

    2023年"五一"假期,文化和旅游行业复苏势头强劲,全国假日市场平稳有序.文化和旅游部数据中心测算,全国国内旅游出游合计2.74亿人次. 据交通部门数据显示,自4月27日铁路&qu ...

  4. 互联网晚报 | 多地明确“五一”假期外地车辆轻微交通违法不予处罚;圆明园回应首次门票售罄;iPhone 15 Pro渲染图曝光...

    多地明确:"五一"假期,外地车辆轻微交通违法不予处罚 据交通发布微博,今年"五一"假期从4月29日开始至5月3日结束,共计5天.七座以下(含七座)小型客车通行收 ...

  5. 【赠书】五一假期福利,OpenCV4最新原理与实战书籍

    五一假期快要到了,本次给大家赠送3本本月新书,这次赠送的书籍是<OpenCV 4机器学习算法原理与编程实战>. 这是一本什么样的书 OpenCV(Open Source Computer ...

  6. 五一假期四天_假期在家上班的12天

    五一假期四天 免责声明:作者拒绝对遵循本文中任何建议的读者所采取的任何纪律处分或法律行动承担任何责任. 在您的组织或公司中,很有可能在假期期间事情放慢1 ,而在这样做的时候,有相应的2机会您可能会在接 ...

  7. 交通运输部:预计五一假期全国客运量2.65亿人次

    5月1日消息,据交通运输部介绍,预计五一假期全国铁路.公路.水路.民航发送的客运量将达2.65亿人次,日均5304万人次,基本恢复到2019年同期水平. 从时间分布来看,交通部预计假期首日将出现客流高 ...

  8. 五一假期期间 全国快递包裹揽投量同比增长约四成

    据国家邮政局公布的数据显示,五一假期期间,受"双品网购节"和农产品网络热销等因素拉动,全国快递包裹揽投量同比增长约四成. 同时,据国家邮政局邮政业安全监管信息系统数据显示,5月1日 ...

  9. 人从众!五一假期全国旅游收入破千亿 你贡献了多少?

    刚刚结束了五一假期回到工作岗位上的你,是不是一上午都昏昏欲睡,持续着"我是谁?我在哪儿?我在干什么?"的状态呢? 不过不要惆怅,做人最重要就是开心,像许多网友一样开始盘算下一次假期 ...

最新文章

  1. C++:随笔5---this指针和类的继承
  2. 数值运算python-Python : 数值以及数值运算
  3. docker安装elasticsearch_Docker 安装 ElasticSearch
  4. JSP自定义标签开发入门
  5. [2018/11/13]图像处理
  6. win7系统如何访问xp系统的服务器,WIN7系统怎么让XP系统访问呢
  7. VS.左侧_蓝黄绿_竖线
  8. 【报告分享】华为:汽车大势所趋,赋能者到引领者.pdf(附下载链接)
  9. 观察者模式(浅谈监听器工作原理)
  10. tomcat6.0 JNDI 配置(图解)
  11. Linux与FreeBSD的多网卡绑定增加服务器流量
  12. C++ QT学习之路----VS2017+QT环境搭建
  13. cass中的地形图打印细节
  14. 小白能读懂的 《手把手教你学DSP(TMS320X281X)》第三章 2020-12-25
  15. 采购计算机申请,采购申请报告格式
  16. Matlab关于转置与共轭转置
  17. R语言随机森林模型回归randomForest
  18. Fiddler简介与功能
  19. Together APP 社交APP
  20. 简记_硬件工程师解读RS-422/RS-485接口

热门文章

  1. 阿里云安全加速 SCDN正式发布公测
  2. 立志从商,如今他把熟食店开到了6家
  3. 【Python 数据科学】连接数据库
  4. message日志输出sbridge: HANDLING MCE MEMORY ERROR错误问题处理
  5. 主动变被动9个例句_LOL手游:改ID不需要改名卡,多个英雄被动技能变主动
  6. 服务宕机问题排查思路
  7. phpexcel官方中文手册---
  8. 爬取北京新发地蔬菜价格
  9. 抖音seo,抖音搜索排名,抖音优化系统,矩阵管理,抖音seo矩阵系统源码技术搭建
  10. python多线程+延时处理