必威体育Betway必威体育官网
当前位置:首页 > IT技术

摩天楼

时间:2019-10-31 07:14:28来源:IT技术作者:seo实验室小编阅读:77次「手机版」
 

摩天楼

摩天楼

题目描述

奶牛公司打算建造一栋摩天楼,共有B层。现在已经建好了第一层,第一层有N个房间,这N个房间从左往右排成一行,第i个房间的号码是A[i],其中1<=A[i]<=9。为了节约成本,公司复制了第一层,然后在第一层上方粘贴了B-1次,这样就能快速完工。由于是复制粘贴的,所以这B层楼完全相同。

FJ对数字很着迷,于是它从第1层楼选择某个房间的号码,再从第2层楼选择某个房间的号码.....最后从第B层楼选择某个房间的号码。FJ把这B个数字从左往右排成一行,就构成了一个大整数,不妨设该整数是X。

请问有FJ有多少种不同的选取方案,使得X % Y = Z。其中Y和Z是输入数据给定的。

由于合法要求的方案数太多,你只需要输出模1000000007结果。

输入格式 2217.in

第一行,四个整数:N,B,Z,Y。

2 <= N <= 50000,1 <= B <= 10^9,0 <= Z < Y<=100, Y >= 2。

第二行,N个整数,第i个整数是A[i]。 1 <= A[i] <=9。

输出格式 2217.out

一个整数。

输入样例 2217.in

输入样例一:

12 1 5 10

3 5 6 7 8 9 5 1 1 1 1 5

输入样例二:

3 2 1 2

6 2 2

输入样例三:

3 2 1 2

3 1 2

输出样例 2217.out

输出样例一:

3

输出样例二:

0

输出样例三:

6

题目大意:

   有B层楼,每层楼有同样的N个数,求在每层楼中取一个数组成一个大的数x,%y后为z的方案数。

样例三解释:

   组成的大楼为:

3 1 2

3 1 2

 6方案分别为:33 31 13 11 2321,这些数被%2都为1。

爆搜(10%):

  好吧,就是dfs每一层取什么。由于层数B一直达到10的九次方,所以很容易就会爆掉。

DP(40%):

   f[i][j]表示,在第i层,此时余数为j,的方案数。

枚举层数i,枚举上一层余数j,枚举这次要选的数k(1~9)。并且k要存在。

状态转移方程为:

f[i ][ (j*10+k)%y ]+=f[ i ][ j ]*num[k]。

时间复杂度为O(b*y*a[i])

正解 矩阵乘法优化(100%) :

  矩阵乘法的具体概念详见矩阵乘法解析总结。

这一个神奇的矩阵是由机智的wyy推出来的。大家可以去看看她的博客可能会比我讲得更清楚。

http://my.csdn.net/littlewyy

当前的第0层的矩阵f[1,0, 0,  0,  0] 表示f[0][0],f[0][1],f[0][2]……f[0][y]的值。(先假设y为5,而只有k=1是存在的)

当前的余数i,加上1~9(k)的某个数,都会变成一个固定的目标值:(i*10+k)%y。

举个例子:假设余数为0,加上1,y为10那么目标值则是1,那么下一层余数为1的矩阵则要变为

f[1,  1,  0,  0,  0]。

而这个矩阵是前一个矩阵乘上“?”得来的呢?因为第一层的第1列(列的编号为0~y-1),要从“?”矩阵的第1列得来。

而前一个矩阵中对应的第0列要,乘“?”矩阵第0行的数,才能达到第一层的矩阵。至于为什么,详见矩阵的性质。

这样两个条件一结合,便是第0行第1列(而把例子转换成文字,则是第 余数 行,第 目标 列)。

我觉得还是好难理解的,如样例三中的“?”矩阵是

1 1 2

1 1 2

第0行第0列表示,有1种使余数为0,下一层还是余数为0的可能,第1行第0列,有一种余数为1变为余数为0的可能。

算了,好像很难解释,迷死了,我昨天想了15分钟以上才想清楚,我理解能力有问题??好吧,感觉矩阵乘法和容斥原理都是很迷很迷的东西。

得出这个固定的转换矩阵以后,就用类似于快速幂的东西。

但是,不知道为什么快速幂里面会炸掉。

于是问题就来了:

  我们发现,在函数里面递归大概5、6层,便会爆空间,交上去只有40分,剩下的全部爆掉。一开始问jt老师,他说可能是因为只分给函数一定的空间,因此定义局部变量很容易炸掉,把它们改成全局变量应该就不会了。

结果还是爆。Zd帮我们把结构体里面的long long改成了int,再在矩阵乘法的计算中,再临时地把矩阵的类型*1LL,然后就AC了。

代码如下:

#include
#include
using namespace std;
const int maxy=105,mod=1000000007;
int n,b,z,y,aa;
long long num[15];
struct henmi
{
	int a[maxy][maxy];
}news,ans,nans,ok;

void init()
{
	ok.a[0][0]=1;
	for(int i=0;i>n>>b>>z>>y;
	for(int i=1;i<=n;i++)
	{
		cin>>aa;
		num[aa]++;
	} 
	init();
	ans=run(b);	
	nans=juzhen(ok,run(b));
	cout<

让我们特别疑惑的是,明明在函数里面没有开任何一个结构

体,也没有开任何一点空间,可是为什么会爆呢?就连jt老师也表示没有遇到过这样的情况。

后来推测估计是因为在快速幂中把矩阵传入矩阵乘法时,会自动预留一个备份空间,然后就会炸掉。

所以,如果把传入这个结构体,改成引用,即本来传入id[c+1]改成传入c+1,就不会炸了。

#include
#include
using namespace std;
const int maxy=105,mod=1000000007;
int n,b,z,y,aa,ceng;
long long num[15];
struct henmi
{
	long long a[maxy][maxy];
}news,ans,now,nans,ok,id[35];

void init()
{
	ok.a[0][0]=1;
	for(int i=0;i>n>>b>>z>>y;
	for(int i=1;i<=n;i++)
	{
		cin>>aa;
		num[aa]++;
	} 
	init();
	id[0]=news;
	run(b,1);
	id[ceng+1]=ok;	
	nans=juzhen(ceng+1,1);
	cout<

文章最后发布于: 2017-08-18 10:44:36

相关阅读

北京监狱开通支付宝扫码存款:每次最多只能存1000元

A5创业网(公众号:iadmin5)1月15日报道,近日北京监狱与支付宝合作,上线了服刑人员综合账务管理系统,为服刑人员提供了狱内支付、家属存款

如何让营销QQ每天1000次邀请不受限制加好友?

营销QQ是拥有10万好友容量的一个企业版QQ,可以每天发出1000次好友邀请,但是很多用户在购买使用之后,发现并不能达到1000次邀请量,经常

浅谈setInterval(aa,1000)与setInterval(aa(),1000)的

一直有个疑惑,在定时器上调用某个方法时,加括号和不加括号有什么区别。今天做了个实验,发现,不加括号定时器会每秒执行一次,加了括号只

做3年社群投入1000万,我都明白了什么?

图片来源图虫:已授站长之家使用声明:本文来自于微信公众号运营研究社公众号(ID:U_quan),作者:陈维贤,授权站长之家转载发布。文章整理自

E1000 与 VMXNET3的 区别

与E1000E和E1000相比,VMXNET3的网络性能更好。本文将解释虚拟网络适配器和第2部分之间的区别,并将演示通过选择半虚拟化适配器可以

分享到:

栏目导航

推荐阅读

热门阅读