这么简单的题才骗到40分QAQ
40分:
很简单,只要n*m扫一遍就好
80分:k^2复杂度
我们发现80分k是很小的,同时我们发现操作的顺序与结果无关,
所以我们先预处理出整个矩阵的sum和
然后对于每一个操作,例如把该行变成10倍,相当于增加九倍,所以我们k次加减....
但是例如我们第一步将第一行变成2倍,第二次将第一列变成3倍,节点1并不是的贡献2+3而是2×3
所以我们k*k扫一边再将虚假的贡献减掉(只有某个点)然后加上真实贡献
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<string> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<cmath> 10 #define int long long 11 #define MAXN 1000101 12 #define ps push_back 13 using namespace std; 14 int read() 15 { 16 int x=0;char c=getchar(); 17 while(c<'0'||c>'9')c=getchar(); 18 while(c>='0'&&c<='9') 19 { 20 x=(x<<1)+(x<<3)+(c^48); 21 c=getchar(); 22 } 23 return x; 24 } 25 int lie[MAXN],hang[MAXN]; 26 int sum_lie[MAXN]; 27 int sum_hang[MAXN]; 28 int n,m;int K;int sum=0; 29 const int mod=1e9+7; 30 vector<int>v1,v2; 31 signed main() 32 { 33 //freopen("text.in","r",stdin); 34 //freopen("wa.out","w",stdout); 35 n=read();m=read();K=read(); 36 for(int i=1;i<=n;++i)hang[i]=1; 37 for(int i=1;i<=m;++i)lie[i]=1; 38 for(int i=1;i<=K;++i) 39 { 40 char c;int x,y; 41 cin>>c; 42 if(c=='R') 43 { 44 x=read();y=read(); 45 hang[x]=(hang[x]*y)%mod; 46 } 47 else 48 { 49 x=read();y=read(); 50 lie[x]=(lie[x]*y)%mod; 51 } 52 } 53 for(int i=1;i<=n;++i) 54 { 55 sum=(sum+(i-1)*m%mod+1+mod)%mod; 56 } 57 sum_lie[1]=sum; 58 for(int i=2;i<=m;++i) 59 { 60 sum_lie[i]=(sum_lie[i-1]+n)%mod; 61 sum=(sum+sum_lie[i])%mod; 62 } 63 for(int i=1;i<=m;++i) 64 sum_hang[1]=(sum_hang[1]+i)%mod; 65 for(int i=2;i<=n;++i) 66 { 67 sum_hang[i]=(sum_hang[i-1]+m*m%mod)%mod; 68 } 69 for(int i=1;i<=n;++i) 70 { 71 if(hang[i]!=1) 72 { 73 v1.ps(i); 74 sum=(sum+(hang[i]-1)*sum_hang[i]+mod)%mod; 75 } 76 } 77 for(int j=1;j<=m;++j) 78 { 79 if(lie[j]!=1) 80 { 81 v2.ps(j); 82 sum=(sum+(lie[j]-1)*sum_lie[j]+mod)%mod; 83 } 84 } 85 for(int i=0;i<v1.size();++i) 86 { 87 for(int j=0;j<v2.size();++j) 88 { 89 int me=v1[i],you=v2[j]; 90 int th=((me-1)*m+you)%mod; 91 sum=(sum+(hang[me]*lie[you]%mod-1)*th-(hang[me]-1)*th-(lie[you]-1)*th+mod)%mod; 92 } 93 } 94 printf("%lld ",(sum+mod)%mod); 95 }
100分 O(n+m)
我们根据一些高中数学知识发现,每一列与每一列之间的变化好像是一定的,
我们不妨先处理行上的变化,
例如第一行变成原来的3倍,那么假设原来这一行是1,2,3......现在是3,6,9.....
我们发现第一列的差值有1变为三倍,那么没一行差值相加就是列与列之间的公差
再处理列的贡献,每一列的初始值都可以递推过来,然后再乘上值的变化,统计答案即可....
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<string> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<cmath> 10 #define int long long 11 #define MAXN 1000101 12 using namespace std; 13 int read() 14 { 15 int x=0;char c=getchar(); 16 while(c<'0'||c>'9')c=getchar(); 17 while(c>='0'&&c<='9') 18 { 19 x=(x<<1)+(x<<3)+(c^48); 20 c=getchar(); 21 } 22 return x; 23 } 24 int lie[MAXN],hang[MAXN]; 25 int n,m;int K; 26 const int mod=1e9+7; 27 signed main() 28 { 29 n=read();m=read();K=read(); 30 for(int i=1;i<=n;++i)hang[i]=1; 31 for(int i=1;i<=m;++i)lie[i]=1; 32 for(int i=1;i<=K;++i) 33 { 34 char c;int x,y; 35 cin>>c; 36 if(c=='R') 37 { 38 x=read();y=read(); 39 hang[x]=(hang[x]*y)%mod; 40 } 41 else 42 { 43 x=read();y=read(); 44 lie[x]=(lie[x]*y)%mod; 45 } 46 } 47 int ans=0; 48 int son_cha=0;int base=0; 49 for(int i=1;i<=n;++i) 50 { 51 son_cha=(son_cha+hang[i])%mod; 52 base=(base+((i-1)*m%mod+1)*hang[i]+mod)%mod; 53 } 54 //printf("base=%lld son_cha=%lld ",base,son_cha); 55 int sum=0; 56 for(int j=1;j<=m;++j) 57 { 58 int me=base; 59 sum=(sum+me*lie[j])%mod; 60 base=(base+son_cha)%mod; 61 } 62 printf("%lld ",sum%mod); 63 }