BZOJ2757: [SCOI2012]Blinker的仰慕者

这题……我一般数位dp都是直接用一个dp把所有东西算完,然而……多组询问每次重新dp会T……然后只好先预处理再查询,然后还搞不了k=0,只好再单独写一个dp……烦死了……

k!=0时,数位的乘积总共就几万种,离散化再预处理转移。f[i][j]表示前i位,乘积为j。k==0时,f[i][2][2][2][2]表示第i位,是否卡下界,是否卡上界,乘积是否为0,是否全是前导0。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int p=20120427;
const int M=20;
const int N=6e4;
int n,q,z1[N][10],z2[N][10];
ll x,y,k,e[M]={1},z3[N],f[M][N][2];
int sol(int r1,ll r2){
	int m=0,r3[M],r4=0;
	for(ll i=r2;i;i/=10)
		r3[m++]=i%10;
	for(int i=1;i<m;++i)
		r4=(r4+f[i][r1][1])%p;
	for(int i=m-1;~i;--i){
		ll r5=r2/e[i+1]*10;
		for(int j=1;j<r3[i];++j)
			if(~z2[r1][j]){
				ll*r6=f[i][z2[r1][j]];
				r4=(r4+r6[1]+(r5+j)*e[i]%p*r6[0])%p;
			}
		r1=z2[r1][r3[i]];
		if(!~r1)break;
	}
	return r4;
}
int cal(ll i){
	return lower_bound(z3,z3+n,i)-z3;
}
namespace ns1{
	int m,z1[M],z2[M],f[M][2][2][2][2][2];
	void sol(){
		for(--x,++y,m=0;y;++m){
			z1[m]=x%10,x/=10;
			z2[m]=y%10,y/=10;
		}
		for(int i=m;i<M;++i)
			z1[i]=z2[i]=0;
		memset(f,0,sizeof f);
		f[m][1][1][0][1][0]=1;
		for(int a=m-1;~a;--a)
			for(int b=1;~b;--b)
				for(int c=1;~c;--c){
					int u=b?z1[a]:0,v=c?z2[a]:9;
					for(int d=1;~d;--d){
						int(*s)[2]=f[a+1][b][c][d];
						for(int e=u;e<=v;++e){
							int(*t)[2][2]=f[a][b&e==z1[a]][c&e==z2[a]];
							(t[d|!e][0][0]+=s[0][0])%=p;
							(t[d|!e][0][1]+=s[0][1]*10+e*s[0][0])%=p;
							(t[0][!e][0]+=s[1][0])%=p;
							(t[0][!e][1]+=e*s[1][0])%=p;
						}
					}
				}
		printf("%d\n",f[0][0][0][1][0][1]);
	}
}
int main(){
	for(int i=1;i<M;++i)
		e[i]=e[i-1]*10;
	const ll v=16e16;
	for(ll a=1;a<v;a*=2)
		for(ll b=a;b<v;b*=3)
			for(ll c=b;c<v;c*=5)
				for(ll d=c;d<v;d*=7)z3[n++]=d;
	sort(z3,z3+n);
	memset(z1,-1,sizeof z1);
	memset(z2,-1,sizeof z2);
	for(int j=0;j<n;++j)
		for(int i=9;i;--i)
			if(z3[j]*i<v)
				z2[z1[j][i]=cal(z3[j]*i)][i]=j;
	f[0][0][0]=1;
	for(int i=0;i<18;++i)
		for(int j=0;j<n;++j){
			ll*s=f[i][j];
			if(!s[0])continue;
			s[0]%=p;
			for(int k=9;k;--k)
				if(~z1[j][k]){
					ll*t=f[i+1][z1[j][k]];
					t[0]+=s[0];
					(t[1]+=s[1]+k*e[i]%p*s[0])%=p;
				}
		}
	scanf("%d",&q);
	while(q--){
		scanf("%lld%lld%lld",&x,&y,&k);
		if(!k)ns1::sol();
		else if(k>=v)puts("0");
		else{
			int j=cal(k);
			if(z3[j]!=k)puts("0");
			else
				printf("%d\n",(sol(j,y+1)-sol(j,x)+p)%p);
		}
	}
}

  

时间: 2024-11-06 02:04:39

BZOJ2757: [SCOI2012]Blinker的仰慕者的相关文章

BZOJ2758 : [SCOI2012]Blinker的噩梦

首先将包含关系建树. 方法是将每个图形拆成上半边和下半边,从左往右扫描线,用Splay从下到上维护扫描线上所有图形. 每次加入一个新的图形$x$的时候,看看它下方第一个图形$y$,如果$y$是上半边,那么$x$的父亲就是$y$,否则是$y$的父亲.用同样的方法可以完成点定位. 然后每次相当于查询两点间的异或和,用树状数组维护dfs序即可. 时间复杂度$O((n+m)\log n)$. #include<cstdio> #include<cmath> #include<algo

BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3352  Solved: 919[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成

BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1594  Solved: 396[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变

BZOJ 2756: [SCOI2012]奇怪的游戏

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3410  Solved: 941[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成

[SCOI2012]滑雪与时间胶囊

2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2362  Solved: 821[Submit][Status][Discuss] Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi.a180285能从景点i 滑到景点j 当且仅当存在一条i 和j 之间的边,且i

BZOJ_2754__[SCOI2012]_喵星球上的点名_(暴力+后缀数组)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2754 给出n个姓名串和m个点名串.求每个点名串在多少人的姓名中出现过(在名中出现或在姓中出现,不能跨越),以及最后每个人被点到多少次. 分析 这种解法是用后缀数组优化一下暴力,(优化了吗?)复杂度并不能保证,然而能A... 我们先把所有名,姓,点名串都接在一个串里面. 然后匹配问题就转化成了后缀的最长公共前缀问题. 但是由于我们讨论问题的对象是名,姓,以及点名串,所以每个部分我们用不同的分隔

【SCOI2012】【BZOJ2753】滑雪与时间胶囊

2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec Memory Limit: 128 MB Submit: 1524 Solved: 536 [Submit][Status][Discuss] Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi.a180285能从景点i 滑到景点j 当且仅当存在一条i 和j 之间的边,且i

[SCOI2012]奇怪的游戏 (网络流)

Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出-1. Input 输入的第一行是一个整数T,表示输入数据有T轮游戏组成. 每轮游戏的第一行有两个整数N和M, 分别代表棋盘的行数和列数. 接下来有N行,每行 M个数. Output 对于每个游戏输出最少能使游戏

2753: [SCOI2012]滑雪与时间胶囊

2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2633  Solved: 910 Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi.a180285能从景点i 滑到景点j 当且仅当存在一条i 和j 之间的边,且i 的高度不小于j. 与其他滑雪爱好者不同,a1802