• 【模拟8.05】矩阵游戏(递推,数学推导)


    这么简单的题才骗到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 }
    80分超时

    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 }
    View Code
  • 相关阅读:
    Python pynput监听键盘
    ProceedingJoinPoint pjp 获取不到方法上
    springcloud- FeginClient 调用统一拦截添加请求头 RequestInterceptor ,被调用服务获取请求头
    多线程-Thread、Runnable 创建线程和调用过程分析
    spring --解析自定义注解SpringAOP(配合@Aspect)
    spring 核心接口之 Ordered
    图标文字
    文字展开和收起
    查找字符串中给定字符串的所有位置
    随机函数与JSON
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11304916.html
Copyright © 2020-2023  润新知