• 2019牛客暑期多校训练营(第八场)


    传送门

    B.Beauty Values (dp)

    •题意

    给你一个序列 a,求序列 a 的任意一个区间 [l,r] 中,元素不同的个数的加和;

    •思路

    定义 dp[ i ] 表示以 i 为结尾的所有区间所包含的元素不同的数的个数;

      即 $dp[i]=sum_{j=1}^{j <= i}f{j,i}$,$f{j,i}$指的是[ j , i ]区间不同数的个数;

      那么,对于 i 位置的数 ai

      ①i 位置为 ai 首次出现的位置:

        $dp[i]=dp[i-1]+i$;

      为什么是+i?

      因为在 [1,i] 比 [1,i-1] 多了个不同的数

      同理 [2,i],[3,i]....[i,i]一共多了i个

      ②[1,i-1] 中 ai 出现的最晚的位置为 j:

        $dp[i]=dp[i-1]+i-j$;

      为什么-j?

      比如x在 2,10,... j位置出现过

      那既然j位置出现过也就是在 [j,i-1] 区间出现过,

      必然在[j-1,i-1],[j-2,i-1] ...   [1,i-1]位置出现过

    也就是多算了j次,要 -j

    •代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int maxn=1e5+5;
     5 int pos[maxn];
     6 int a[maxn];
     7 ll dp[maxn];
     8 int main()
     9 {
    10     int n;
    11     cin>>n;
    12     dp[1]=1;
    13     for(int i=1;i<=n;i++)
    14     {
    15         cin>>a[i];
    16         if(i>1)
    17             dp[i]=dp[i-1]+i-pos[a[i]];
    18         pos[a[i]]=i;
    19     }
    20     ll ans=0;
    21     for(int i=1;i<=n;i++)
    22         ans+=dp[i];
    23     cout<<ans<<endl;
    24 }
    View Code

    C.CDMA(构造)

    •题意

      假设序列 s,t 都只含有 n 个元素;

      定义 $scdot t=sum_{i=1}^{i<=n}s_icdot t_i$ ;

      构造一个 m×m 的矩阵 a,其中 m = 2k , 1 ≤k ≤ 10,使其满足:

      ①矩阵中只包含 -1,1;

      ②任意不同的两行 a[ i ],a[ j ], a[ i ]·a[ j ] = 0;

    •题解

      根据 m = 2 , m = 4 的满足条件的矩阵找规律;

      m = 2:

      $left( egin{array}{cc} 1 & 1 \ 1 & -1 end{array} ight)$

      m = 4:

      $left( egin{array}{cccc} 1 & 1 & 1 & 1 \ 1 & -1 & 1 & -1 \ 1 & 1 & -1 & -1 \ 1 & -1 & -1 & 1 \ end{array} ight)$

      m = 4 时,从行,列的中间分开,分成成 4 个 2×2 的子矩阵,你会发现,前三个子矩阵 = (m=2时的矩阵);

      最后一个子矩阵 = (m=2时的矩阵取反);

      根据上述规律,可以求出 m = 8,16,....,1024 时的满足条件的矩阵;

    •代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 string base[2000];
     4 int m;
     5 void Slove()
     6 {
     7     for(int k=2;k<=10;k++)
     8     {
     9         m=1<<k;
    10         for(int i=0;i<m/2;i++)
    11             base[i]+=base[i]; ///double
    12         for(int i=m/2;i<m;i++)
    13         {
    14             base[i]=base[i%(m/2)];
    15 
    16             for(int j=m/2;j<m;j++)
    17                  base[i][j]=(base[i][j]=='0'?'1':'0');
    18         }
    19     }
    20 }
    21 int main()
    22 {
    23     int m;
    24     cin>>m;
    25     base[0]="11";
    26     base[1]="10";
    27     //0代表-1 便于用字符表示
    28 
    29     Slove();
    30     for(int i=0;i<m;i++)
    31         for(int j=0;j<m;j++)
    32             printf("%d%c",base[i][j]=='0'?-1:1,j==m-1?'
    ':' ');
    33 }
    View Code

    G.Gemstones(模拟)

    •题意

      给你一个只包含大写字母的串 s;

      如果相邻的三个字符为相同的字母,那么,便可将这三个相同的字母消去;

      求最多可以消去多少次;

    •思路

    用栈模拟

    当栈中大于两个时,往里加入时判断是否构成相同三字符,

    若能构成则消去,不能构成则继续加入

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int maxn=1e5+5;
     5 stack<char> sta;
     6 char s[maxn];
     7 int main()
     8 {
     9     scanf("%s",s+1);
    10     int len=strlen(s+1);
    11     bool flag;
    12     int ans=0;
    13 
    14     for(int i=1;i<=len;i++)
    15     {
    16         flag=true;
    17         while(flag)
    18         {
    19             flag=false;
    20             if(sta.size()>=2)
    21             {
    22                 char a=sta.top();
    23                 sta.pop();
    24                 char b=sta.top();
    25                 sta.pop();
    26                 if(s[i]==a&&a==b)
    27                 {
    28                     flag=true;
    29                     i++;
    30                     ans++;
    31                 }
    32                 else
    33                 {
    34                     sta.push(b);
    35                     sta.push(a);
    36 
    37                 }
    38             }
    39         }
    40         sta.push(s[i]);
    41     }
    42 
    43     printf("%d
    ",ans);
    44 }
    View Code
  • 相关阅读:
    应用程序框架实战十三:DDD分层架构之我见
    Util应用程序框架公共操作类(三):数据类型转换公共操作类(扩展篇)
    Util应用程序框架公共操作类(二):数据类型转换公共操作类(源码篇)
    不能使用 float 和 double 来表示金额等精确的值
    JVM 字节码指令手册
    MyBatis: Invalid bound statement (not found)错误的可能原因
    Oracle:ORA-01219:database not open:queries allowed on fixed tables/views only
    手写 Spring MVC
    8080 端口被占用的解决方法 netstat -ano;taskkill (命令行)
    Java 工具类 IpUtil
  • 原文地址:https://www.cnblogs.com/MMMinoz/p/11332708.html
Copyright © 2020-2023  润新知