题目
容易题
昨天考试考了这道 容易题 ,不知道怎么想的,打了个DP,居然拿了70,先定义 dis[ i ] [ j ] 表示最后是第 i 行,最后一个数是 j 的结果,vis[ i ] [ j ]表示第i行j是否可选,然后想到枚举到第k,然后后面的数其实是可以用乘法分配律结合,所以转移方程就是
[dis[ i ] [ j ] = sumlimits_{k=1}^{n} {dis[ i - 1 ][k] imes 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 ] = sumlimits_{k=1}^{n} dis[i][k]
]
然后又发现
[dis[i][k] = sumlimits_{j=1}^{n} k imes sum[i-1]
]
最后可以得出递推式
[sum[i] = sum[i-1] imes sumlimits_{j=1}^{n}j(vis[i-1][j]=0)
]
于是这就是一个真的简单题了,最后结果就是
[ans = prodlimits_{i=1}^{n} sumlimits_{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
",ans);
return 0;
}