【HDU5564 BestCoder Round 62 (div1)B】【DP转矩阵快速幂】Clarke and digits 长度在[l,r]范围内7倍数数个数要求相邻两位不为K

原创 2015年11月18日 17:08:55
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int G=71;//矩阵大小
const int Z=1e9+7;//取模数
struct MX
{
	int v[G][G];
	void O(){MS(v,0);}
	void E(){MS(v,0);for(int i=0;i<G;i++)v[i][i]=1;}
	MX operator * (const MX &b) const
	{
		MX c;c.O();
		for(int i=0;i<G;i++)
		{
			for(int j=0;j<G;j++)
			{
				for(int k=0;k<G;k++)
				{
					c.v[i][j]=(c.v[i][j]+(LL)v[i][k]*b.v[k][j])%Z;
				}
			}
		}
		return c;
	}
	MX operator ^ (int p) const
	{
		MX y;y.E();
		MX x;MC(x.v,v);
		while(p)
		{
			if(p&1)y=y*x;
			x=x*x;
			p>>=1;
		}
		return y;
	}
}a,b,c;
int casenum,casei;
int l,r,K;
int main()
{
	a.O();
	for(int i=1;i<10;i++)
	{
		int j=i%7;
		int o=j*10+i;
		a.v[0][o]=1;
	}
	scanf("%d",&casenum);
	for(casei=1;casei<=casenum;casei++)
	{
		scanf("%d%d%d",&l,&r,&K);//--l;--r;
		b.O();
		for(int i=0;i<7;i++)//枚举余数
		{
			for(int j=0;j<10;j++)//枚举尾数
			{
				int o1=i*10+j;
				for(int u=0;u<7;u++)//枚举余数
				{
					for(int v=0;v<10;v++)//枚举尾数
					{
						int o2=u*10+v;
						b.v[o1][o2]=(j+v!=K&&(i*10+v)%7==u);
					}
				}
			}
		}
		for(int j=0;j<10;j++)b.v[j][70]=1;
		b.v[70][70]=1;
		c=a*(b^r);int ansr=c.v[0][70];
		c=a*(b^(l-1));int ansl=c.v[0][70];
		int ans=(ansr+Z-ansl)%Z;
		printf("%d\n",ans);
	}
	return 0;
}
/*
【trick&&吐槽】
不要一开始就思考解决问题,
可以先简化数据规模,从小数据入手,再优化,就能AC看起来比较难的题目啦!

【题意】
对于一个正整数,如果其恰好是7的倍数,而且任意相邻两位的数都不为K,那么我们称这个数为7-K number,
现在问你,长度在[l,r]之间的7-K number的个数是多少,输出其mod (1e9+7)的值。
其中,K∈[0,18],l<=r<=1e9

【类型】
DP转矩阵快速幂

【分析】
首先,[l,r]大的我们不敢DP。但是我们应该先想到DP的做法,再进而考虑优化与转移——
怎么DP呢?要先考虑状态的设置——
用f[i][j][k]表示长度为i的串,尾数是j,目前%7的余数为k的数串的个数。
我们考虑使得这个数串*10,然后再加上一个尾数。这种做法恰好可以避免出现前导0的情况。
初始情况下,有f[1][x][x%7]=1; x∈[1,9]
那么我们枚举下一位的尾数u,u∈[0,9]便有状态转移方程——
f[i+1][u][(k*10+u)%7]+=f[i][j][k],转移的条件是u+j≠K
最后f[l~r][0~9][0]就是答案
然而这个DP的时间复杂度是 长度(i)*10(j)*7(k)*10(u),长度太大,于是时间复杂度爆炸。
我们寻求的解决办法便是——矩阵快速幂。
(尾数,余数)的可能性一共也不过只有70种,我们列出一个70*70的矩阵b[][]
我们把(余数*10+尾数)定义为状态,那么b[i][j]=1则表示由状态i向状态j可以转移
这样我们求b^r和b^(l-1),a*(b^r)-a*(b^(l-1))就是答案啦。    ?!?!   
QwQ   ?!?!  并不对!这个是错误的。
a*(b^r)对应的是长度恰好为r,b^(l-1)对应的是长度恰好为l-1。
正确的做法是怎样呢?
我们需要累加一个前缀和,于是引入第71维。
使得b[0~9][70]都为1,b[70][70]也为1.
这样a*(b^p),得到的是这个DP转移[0,p-1]次(即长度在[1,p]范围下)的合法数串的个数
于是这样,a*(b^r)-a*(b^(l-1))就是答案啦。

【时间复杂度&&优化】
O(T * 71^3 * (log(r)+log(l)) ),运算上限大概是7e7,可以在1s内AC~

*/


版权声明:题解中哪里写错请一定要指出来QwQ 转载还请注明下出处哦,谢谢^_^ 举报

相关文章推荐

【HDU5564 BestCoder Round 62 (div1)B】【DP转矩阵快速幂】Clarke and digits 长度在[l,r]范围内7倍数数个数要求相邻两位不为K

#include #include #include #include #include #include #include #include #include #include #include #...

hdu5564 Clarke and digits

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

hdu 5564 Clarke and digits (dp+矩阵加速)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 问题描述 克拉克是一名人格分裂患者。某一天,克拉克变成了一个研究人员,在研究数字。 ...

hdu 5667 BestCoder Round #80 矩阵快速幂

Sequence    Accepts: 59    Submissions: 650  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit...

hdu 5607 BestCoder Round #68 (矩阵快速幂)

题意: graph    Accepts: 9    Submissions: 61  Time Limit: 8000/4000 MS (Java/Others)   ...

HDU2089 不要62 (数位DP)

传送门 数位DP的入门题,看了半天才看懂。。。 题解:http://blog.csdn.net/gengmingrui/article/details/47957397 这里再解释一下,dp[i...

HDU2089:不要62(数位DP)

Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来...

hdu2089 不要62 数位dp

题意:中文题。。自己看。。 思路:

HDU2089 不要62[数位DP]

A - 不要62  HDU - 2089  题解: 统计[n,m]中不含4 或者 62的数有多少个,最基础的数位DP题目,首先判断有4就直接continue,然后判断如果前一个是6,下一个是2...

Hdu 2089 不要62(数位dp入门)

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)