小米网络赛 第二场 F题 Modulo Nine

Pro:
https://ac.nowcoder.com/acm/contest/7502/F
在n个位置填入0~9的数字,再给出m个限制
每个限制\([li,ri]\)表示这个区间的区间乘积为9的倍数
求方案数
Sol:
直接上题解

#include<bits/stdc++.h>
#define N 2200
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
const int h=3,ki=149,mo=1e9+7;
inline int inc(int x,int k){x+=k;return x<mo?x:x-mo;}
inline int dec(int x,int k){x-=k;return x>=0?x:x+mo;}
int ksm(int x,int k)
{
	int ans=1;
	while(k){if(k&1)ans=1ll*ans*x%mo;k>>=1;x=1ll*x*x%mo;}
	return ans;
}
int inv(int x){return ksm(x,mo-2);}
inline int read()
{
	char ch=0;int x=0,flag=1;
	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
	return x*flag;
}
inline void write(int x)
{
	if(!x)return (void)putchar(48);
	if(x<0)putchar(45),x=-x;
	int len=0,p[20];
	while(x)p[++len]=x%10,x/=10;
	for(int i=len;i>=1;i--)putchar(p[i]+48);
}
const db eps=1e-7,inf=1e9+7,pi=acos(-1);
inline db Read(){db x;scanf("%lf",&x);return x;}
inline void Write(db x){printf("%lf",x);}
int f[N],s[N],dp[N][N];
bool work()
{
	int n,m;
	if(scanf("%d%d",&n,&m)==-1)return false;
	for(int i=0;i<=n+1;i++)
	{
		f[i]=s[i]=0;
		for(int j=0;j<=n+1;j++)dp[i][j]=0;
	}
	for(int i=1;i<=m;i++){int l=read(),r=read();f[r]=max(f[r],l);}
	for(int i=2;i<=n;i++)f[i]=max(f[i],f[i-1]);
	dp[0][0]=1;s[0]=1;int v3=inv(3);
	for(int i=0;i<=n-1;i++)
	{	 
		//s[k]=∑(f[i]<=t<=i) 
		for(int k=f[i];k<=i;k++)dp[i+1][i+1]=inc(dp[i+1][i+1],1ll*v3*s[k]%mo);s[i+1]=inc(s[i+1],dp[i+1][i+1]);
			
		for(int k=f[i+1];k<i+1;k++)dp[i+1][k]=1ll*v3*s[k]%mo,s[i+1]=inc(s[i+1],dp[i+1][k]);
		
		//s[k]=∑(f[i+1]<=t<=i+1) 
		for(int k=f[i];k<=i;k++)for(int t=f[i];t<f[i+1];t++)s[k]=dec(s[k],dp[k][t]);
	}	
	int ans=0;
	for(int i=f[n];i<=n;i++)for(int j=f[n];j<=i;j++)ans=inc(ans,dp[i][j]);
	ans=1ll*ans*ksm(6,n)%mo;write(ans);putchar('\n');return true;
}
int main()
{
	while(work());
	return 0;
}
posted @ 2020-11-08 21:12  Creed-qwq  阅读(118)  评论(0编辑  收藏  举报