其他分享
首页 > 其他分享> > luogu P5307 [COCI2019] Mobitel

luogu P5307 [COCI2019] Mobitel

作者:互联网

题面传送门
显然有\(O(nmw)\)的dp但是不能过。
我们发现对于\([w/2+1,w-1]\)这一段区间内的数\(\times 2\)都是一样的。这启示我们压起来。
根据整除分块原理只有\(O(\sqrt w)\)个不同的数。
所以就可以优化到\(O(nm\sqrt w)\)了。
code:

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<map>
#include<set>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define S 1100000
#define N 300
#define K 1000
#define W 1000000
#define mod 1000000007
using namespace std;
int n,nows[K+5<<1],g[W+5],m,w,a[N+5][N+5],head,last,now;ll dp[3][N+5][K+5<<1];
int main(){
	freopen("1.in","r",stdin);
	re int i,j,k;scanf("%d%d%d",&n,&m,&w);w--;
	for(i=w;i;i--) nows[head]^(w/i)&&(nows[++head]=w/i,g[w/i]=head);
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++)scanf("%d",&a[i][j]);
	}dp[1][1][g[w/a[1][1]]]++;
	for(i=1;i<=n;i++){
		now=i&1;last=now^1;memset(dp[last],0,sizeof(dp[last]));
		for(j=1;j<=m;j++){
			for(k=0;k<=head;k++) dp[now][j][k]%=mod,j^m&&(dp[now][j+1][g[nows[k]/a[i][j+1]]]+=dp[now][j][k]),i^n&&(dp[last][j][g[nows[k]/a[i+1][j]]]+=dp[now][j][k]);
		}
	}
	printf("%lld\n",dp[n&1][m][0]);
}

标签:code,COCI2019,min,传送门,luogu,sqrt,include,P5307,define
来源: https://www.cnblogs.com/275307894a/p/14766228.html