常州Day4题解

1. 高精度

这题略水,字符串可过,还不加压位等,操作只有BitShift和add/sub,不过编程复杂度有些高.(输出都是二进制我能说些什么...)

2. N皇后问题 (警告! 不是平时你见到的N皇后问题...是一道Hash的模拟题,N皇后的位置都给你了,就是统计)

二级标题很详细了,搜索那些解N皇后问题的千万莫戳进来.

3. Sam数

一道比较有意思的题.

题意是,给定一个k,求所有k位数中所有相邻两位数差都小于等于2的数.输出$\mod{10^9+7}$

说的不够明白.来个例子:

$2134678$ 这是一个符合要求的7阶Sam数.

$6987688$ 这个不符合,$\left| 9-6\right|=3>2$

很明显,当$k=1$时输出$10$.

当$k=2$时,很明显最高位不可为0.

于是第一位只能为$1~9$.

第二位呢?显然不可能是$0~10$.限制条件摆那儿呢!

于是想到,第二位是$0$的时候有两种可能,即$10$和$20$.这是从第一位是$0,1,2$的地方推导来的.

于是递推式很明显,$F[i,j]=\sum_{n=j-2}^{j+2}F[i-1,n]\text{While n}\in\text{0~9}$

可是数据范围:

$30\% k\le 10^6,60\% k\le 10^{12},100\% 10^{18}$

吓,$10^6 \cdot 10$都基本爆空间好么? 逗我呢?

注意到每次递推只需用到前一次的结果,用滚动数组即可. 30分到手.

但是,十的十八次位数这是要闹那样!!!

车到山前必有路(话说我当时还没想到).

注意这是线性递推.每次递推后的$F[i]$都是前一次值的线性组合($\text{linear combination}$),而这事可以用矩阵乘法解决.矩阵乘法遵守结合率,可以使用二分快速幂在$O(\log{n})$时间内求出.至于矩阵乘法的复杂度...他不会随着输入数据的上升而上升,$O(n^3)$中n恒等于10,即是常数时间,只是常数比较大.

时间复杂度是$O(1000 \cdot \log(n))=O(\log{n})$.

矩阵方法详细参数:

变换矩阵:

$tr=\left[ \begin{array} {lcr}
1 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\
1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 0 \\
0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 \\
0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 \\
0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 \\
0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1
\end{array} \right]$

初始向量:

$i=\left[ \begin{array} {lcr}
0 \\
1 \\
1 \\
1 \\
1 \\
1 \\
1 \\
1 \\
1 \\
1
\end{array} \right]$

递推结果为$c = tr^k \cdot i$

结果

$$sum=\sum_{i \in c}c[i]$$

注意随时求余.特判k=1.

最后一题代码(前两题还要?自己写去..)

#include "cstdio"
#define modulo 1000000007
#include "cstring"
struct mat{
	long long m[10][10],i,j,k,t;
	void cpy(mat b){
		for(i=0;i<10;++i)
			for(j=0;j<10;++j)
				m[i][j]=b.m[i][j];
	}
	void mul(mat a){
		mat tempa;
		for(i=0;i<10;++i){
			for(j=0;j<10;++j){
				t=0;
				for(k=0;k<10;++k){
					t+=m[k][i]*a.m[j][k];
				}
				tempa.m[i][j]=t % modulo;
			}
		}
		cpy(tempa);
	}
	void toUnit(){
		memset(m,0,sizeof(m));
		for(i=0;i<10;++i){
			m[i][i]=1;//unit in matrix computation,oops...
		}
	}
} matt,tt;
struct vect{
	long long m[10],tm;
	int i,j;
	void mul(mat a){
		for(i=0;i<10;++i){
			tm=0;
			for(j=0;j<10;++j){
				tm+=m[i]*a.m[i][j];
			}
			m[i]=tm % modulo;
		}
	}
} vec;
long long n,ac;
void fastPow(long long n){
	if(n&1){
		tt.cpy(matt);
	}else{
		tt.toUnit();
	}
	while(n>>=1){
		matt.mul(matt);
		if(n&1){
			tt.mul(matt);
		}
	}
}
const long long pa[10]={0,1,1,1,1,1,1,1,1,1};
const long long pb[10][10]={
	{1,1,1,0,0,0,0,0,0,0},
	{1,1,1,1,0,0,0,0,0,0},
	{1,1,1,1,1,0,0,0,0,0},
	{0,1,1,1,1,1,0,0,0,0},
	{0,0,1,1,1,1,1,0,0,0},
	{0,0,0,1,1,1,1,1,0,0},
	{0,0,0,0,1,1,1,1,1,0},
	{0,0,0,0,0,1,1,1,1,1},
	{0,0,0,0,0,0,1,1,1,1},
	{0,0,0,0,0,0,0,1,1,1}
};
int main(){
	scanf("%lld",&n);
	if(n==1){
		printf("10\n");
		return 0;
	}
	memcpy(vec.m,pa,sizeof(pa));
	memcpy(matt.m,pb,sizeof(pb));

	fastPow(n-1);//幂次修正
	vec.mul(tt);
	ac=0;
	for(int i=0;i<10;++i){
		ac+=vec.m[i];
	}
	printf("%lld\n",ac % modulo);
	return 0;
}

常州Day4题解,布布扣,bubuko.com

时间: 2024-08-09 00:56:09

常州Day4题解的相关文章

块池是属于单个命名空间的一组块。

块池( Block Pool)     块池是属于单个命名空间的一组块.     每一个datanode为所有的block pool存储块.     Datanode是一个物理概念,而block pool是一个重新将block划分的逻辑概念.     同一个datanode中可以存着属于多个block pool的多个块.     Block pool允许一个命名空间在不通知其他命名空间的情况下为一个新的block创建Block ID.     一个Namenode失效不会影响其下的datanod

【2016常州一中夏令营Day4】

小 W 走迷宫[问题描述]小 W 被小 M 困在了一个方格矩阵迷宫里,矩阵边界在无穷远处,我们做出如下的假设:a. 每走一步时,只能从当前方格移动一格,走到某个相邻的方格上:b. 走过的格子立即塌陷无法再走第二次:c. 只能向北.东.西三个方向走.小 W 走了没多久就累坏了,他很想知道如果允许在方格矩阵上走 N 步,共有多少种不同的方案.( 开始时小 W 就在方格矩阵上的任意位置, 2 种走法只要有一步不一样,即被认为是不同的方案)[输入格式]一行输入 N.[输出格式]一行输出方案个数.[输入输

【数论Day4】 数学 题解

题目:http://www.cnblogs.com/ljc20020730/p/7041033.html 1.离散函数(function.pas/c/cpp) 观察右图,图像必须符合任意两点都在直线的下方.故三条直线中只有相邻两顶点之间的连线的斜率最大.故得出一个规律:最大斜率的直线一定由x坐标相邻的两点确定,即Xi-Xi-1最大的点对. O(n)枚举,通过本题. var n,i,ans1,ans2,maxk:longint; a:array[1..200000]of longint; begi

常州大学新生寒假训练会试 题解

[题目链接] A - 添加逗号 注意是从后往前三个三个加逗号,最前面不允许有逗号 #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; char s[maxn]; char ans[maxn]; int sz; int main() { scanf("%s", s); int len = strlen(s); sz = 0; int t = 0; for(int i = len -

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

(leetcode题解)Pascal&#39;s Triangle

Pascal's Triangle  Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题意实现一个杨辉三角. 这道题只要注意了边界条件应该很好实现出来,C++实现如下 vector<vector<int>> generate(int

2017ZZUACM省赛选拔试题部分题解----谨以纪念我这卡线滚粗的美好经历

写在前面: 其实心里有些小小的不爽又有点小小的舒畅,为啥捏?不爽当然是因为没被选拔上啦,舒畅捏则是因为没被选拔上反而让自己警醒,学长也提点很多很多."沉下去,然后一战成名"学长如是对我说,我很开心.其实这完全算不算是题解,只是我个人的一些小想法而已.而且到现在还有一题不会...让自己长点记性吧. 题目 A :聪明的田鼠 Time Limit: 1 Sec Memory Limit: 128 MB Description 田鼠MIUMIU来到了一片农田,农田可以看成是一个M*N个方格的矩