【HAOI2012】容易题
终于自己做出一道题了quq
原题:
为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:
有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!
n<=10^9,m<=10^9,k<=10^5,1<=y<=n,1<=x<=m
这道题挺有意思的,用到了很多基础的知识(其实就是因为简单好写容易AC_(:3 」∠)_
小学级结论:
假设三个位置分别能用三个数a1,a2,a3,b1,b2,b3,c1,c2,c3,手玩一下就可以发现答案是(a1+a2+a3)*(b1+b2+b3)*(c1+c2+c3)
然后每个位置初始的和是(1+n)*n/2,如果有数不能选就直接减掉,数据很良心地提示可能会有重复的(如果不提示我估计想不到
然后搞一搞就行了
注意到m<=1e9,时空爆炸
其实也很好搞,离散化一个,先计算有数被删掉的,剩下的位置的数的和都是(1+n)*n/2,快速幂搞一搞就行了
判重怎么办呐
最开始我想的是set,map,或者搞个平衡树?
然后发现,搞个毛啊,离线即可
这么简单的题WA了两发quq(最开始没考虑到m<=1e9没离散直接从1到m计算了
还要提升思考的精细程度啊……
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define ll long long 8 const int dalao=1000000007; 9 int rd(){int z=0,mk=1; char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 11 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 12 return z*mk; 13 } 14 struct dcd{int x,y;}a[110000]; 15 bool cmp(dcd x,dcd y){ return (x.x==y.x)?(x.y<y.y):(x.x<y.x);} 16 int n,m,t; ll M; 17 ll bwl[110000]; 18 int c[110000],b[110000],tt=0; 19 ll qckpw(ll x,int y){ 20 ll z=1,bs=x; 21 while(y){ 22 if(y&1) z=(z*bs)%dalao; 23 bs=(bs*bs)%dalao; 24 y>>=1; 25 } 26 return z; 27 } 28 int bnrsch(ll x){ 29 int l=1,r=tt,md; 30 while(l+1<r) md=(l+r)>>1,(b[md]<=x ? l : r)=md; 31 return b[r]==x ? r : l; 32 } 33 int main(){//freopen("ddd.in","r",stdin); 34 cin>>m>>n>>t; M=((ll)(1+m)*m/2)%dalao; 35 for(int i=1;i<=t;++i) a[i].x=rd(),a[i].y=rd(),c[i]=a[i].x; 36 sort(a+1,a+t+1,cmp); 37 sort(c+1,c+t+1); 38 for(int i=1;i<=t;++i)if(c[i]!=c[i-1]) b[++tt]=c[i]; 39 for(int i=1;i<=tt;++i) bwl[i]=M; 40 for(int i=1;i<=t;++i)if(!(a[i].x==a[i-1].x && a[i].y==a[i-1].y)) 41 bwl[bnrsch(a[i].x)]=(bwl[bnrsch(a[i].x)]-a[i].y+dalao)%dalao; 42 ll ans=1; 43 for(int i=1;i<=tt;++i) ans=(ans*bwl[i])%dalao; 44 cout<<(ans*qckpw(M,n-tt))%dalao<<endl; 45 return 0; 46 }