简单题 题解
题目
容易题
昨天考试考了这道 容易题 ,不知道怎么想的,打了个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;
}