简单题 题解

题目

容易题

昨天考试考了这道 容易题 ,不知道怎么想的,打了个DP,居然拿了70,先定义 dis[ i ] [ j ] 表示最后是第 i 行,最后一个数是 j 的结果,vis[ i ] [ j ]表示第i行j是否可选,然后想到枚举到第k,然后后面的数其实是可以用乘法分配律结合,所以转移方程就是

\[dis[ i ] [ j ] = \sum\limits_{k=1}^{n} {dis[ i - 1 ][k] \times j } ( vis[ i ] [ j ] = 0 ) \]

然后前缀和优化从($ n^3 \()优化到(\) n^2 $),最后答案就是sum[ m ] ,这样就可以拿到 70 分 的好成绩

\(Code\)

for(int i=1,x,y;i<=k;++i){
	x=read();y=read();
	vis[x][y]=1;
}
for(int i=1;i<=n;++i){
	if(vis[1][i])continue;
	dis[1][i]=i;sum[1]=(sum[1]+i)%mod;
}
for(int i=2;i<=m;++i){
	for(int j=1;j<=n;++j){
		if(vis[i][j])continue;
		dis[i][j]=(dis[i][j]+j*sum[i-1]%mod)%mod;
	}
	for(int j=1;j<=n;++j)
		sum[i]=(sum[i]+dis[i][j])%mod;
}

现在再想一下,上面的式子其实就是

\[sum[ i ] = \sum\limits_{k=1}^{n} dis[i][k] \]

然后又发现

\[dis[i][k] = \sum\limits_{j=1}^{n} k\times sum[i-1] \]

最后可以得出递推式

\[sum[i] = sum[i-1] \times \sum\limits_{j=1}^{n}j(vis[i-1][j]=0) \]

于是这就是一个真的简单题了,最后结果就是

\[ans = \prod\limits_{i=1}^{n} \sum\limits_{j=1}^{n}j \]

这就是没有限制的式子,如果有限制的话只需要在乘的时候减去即可
比如\(n == 2,m == 3\)时,$ k==2 $, \((1,1),(2,2)\)不能选,\(ans=(1) * (2) * (1+2)\)
然后看到 n 到了 \(1e9\), k 只有 \(1e5\)所以从 k 入手,先用结构体存起来k个限制,排一下序,减去,剩下的跑一个快速幂即可,同时要注意去重,很多大佬用是用map去重,一开始看的迷迷糊糊的(可能是我太菜了),于是我用来一个STL的神奇函数unique,这个函数可以做到去重。
,然后利用map映射记录每个被修改的x对应的值,乘进去即可。最后提一点,因为 n 太大,用累加直接 T 飞,一定要用等差数列求和算(死了3次才的出的宝贵经验,应该不会有人和我一样傻吧

\(Code\)

#include <bits/stdc++.h>
using namespace std;
#define gc getchar()
const long long mod=1e9+7;
long long n,m,k,cnt;
long long ans=1,s;
long long mp[1000000+10];
map<int,long long> ma;
struct gdx{
	long long x,y;
	friend bool operator < (const gdx &A,const gdx &B){
		return A.x < B.x;
	}
	friend bool operator == (const gdx &A,const gdx &B){
		return (A.x==B.x&&A.y==B.y);
	}
}a[1000000+10];

inline int read(){
	int r=0,l=1;char ch=gc;
	while(!isdigit(ch)){if(ch=='-')l=-1;ch=gc;}
	while(isdigit(ch)){r=(r<<3)+(r<<1)+ch-'0';ch=gc;}
	return r*l;
}

inline long long ksm(long long x,long long y){
	long long ans=1;
	while(y){
		if(y&1)ans=ans*x%mod;
		y>>=1;x=x*x%mod;
	}
	return ans;
}

int main(){
	freopen("easy.in","r",stdin);
	freopen("easy.out","w",stdout);
	n=read();m=read();k=read();
	s=n*(n+1)/2%mod;
	for(int i=1,x,y;i<=k;++i)
		a[i].x=read(),a[i].y=read();
	sort(a+1,a+k+1);
	int p=unique(a+1,a+k+1)-a;p--;
	for(int i=1,l=0;i<=p;++i){
		if(l!=a[i].x){
			mp[++cnt]=a[i].x;
			ma[a[i].x]=s;l=a[i].x;
		}
		ma[a[i].x]=(ma[a[i].x]-a[i].y+mod)%mod;
	}
	for(int i=1;i<=cnt;++i)ans=ans*ma[mp[i]]%mod;
	ans=ans*ksm(s,m-cnt)%mod;
	printf("%lld\n",ans);
	return 0;
}
posted @ 2020-10-10 08:21  goote~  阅读(135)  评论(3编辑  收藏  举报
Live2D