暑假7.29 Test

Posted ljb666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暑假7.29 Test相关的知识,希望对你有一定的参考价值。

似乎是打表+暴力专场,可惜我什么规律也找不出来,一题模拟乱搞,二三题神仙打表。

T1懒得写题面了 一句话题意,就是问你在一个n*m的01矩阵中有多少个k*k的子矩阵包含1

正解二维前缀和,考试的时候我想的是暴力模拟,把所有子矩阵扫一遍,打标记就得了。暴力模拟也挺好做,虽然自己造的大数据炸掉了,但是交上去手动开O2+读优就可以艹过去。复杂度O(n*m)对于这道题足够了。

代码:

技术图片
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int N=1550;
inline void read(int &re)

    char ch;
    while((ch=getchar())<0||ch>1);
    re=ch-48;

int n,m,k;
int jz;
int sx,sy,ex,ey;
long long tot;
long long spe;
int x[N],y[N];
int cnt;
int flag1[N][N];
int flag2[N][N];
int main()
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(register int i=1;i<=n;i++)
        for(register int j=1;j<=m;j++)
            read(jz);//一定要读优
            if(jz==1)
                spe++;
                x[++cnt]=j;
                y[cnt]=i;
            
        
    
    if(k==1)//等于1直接输出
        printf("%lld\\n",spe);
        return 0;
    
    sx=1,sy=1,ex=k,ey=k;
    while(ex<=m&&ey<=n)
        for(register int i=1;i<=cnt;i++)
            if(x[i]>=sx&&y[i]>=sy&&x[i]<=ex&&y[i]<=ey&&((!flag1[sx][sy])||(!flag2[ex][ey])))//在范围内
                tot++;
                if(!flag1[sx][sy]) flag1[sx][sy]=1;//打标记
                if(!flag2[ex][ey]) flag2[ex][ey]=1;
            
        
        sx+=1;
        ex+=1;
        if(sx>m-k+1)//扫下一行
            sx=1;
            ex=k;
            sy+=1;
            ey+=1;
        
    
    printf("%lld\\n",tot);
    return 0;
 
View Code

不敢保证是完全正确的,给出std:

技术图片
#include <bits/stdc++.h>
using namespace std;
const int N = 1033;
char s[N][N];
int n, m, k, a[N][N];
int main() 
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
  scanf("%d%d%d", &n, &m, &k);
  for (int i = 1; i <= n; i++) 
    scanf("%s", s[i] + 1);
  
  int all = (n + 1 - k) * (m + 1 - k);
  for (int i = 1; i <= n; i++) 
    for (int j = 1; j <= m; j++) 
      if (s[i][j] == 1) 
        a[i][j] = 0;
       else 
        a[i][j] = min(a[i - 1][j - 1], min(a[i - 1][j], a[i][j - 1])) + 1;
      
      if (a[i][j] >= k) 
        all--;
      
    
  
  printf("%d\\n", all);
View Code

T2 就是问你1-n中约数的约数个数和最大的数是谁 打表可做,不过n的范围过大。而且我巨臭的打表只能打前两个点。题解如下:

技术图片

std:

技术图片
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int pri[] = 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53;
ll n, coef, cur, ans, ans2;

void dfs(int p, ll cur, ll coef, int last) 
  assert(cur > 0 && coef > 0);
  if (coef > ans) 
    ans = coef;
    ans2 = cur;
   else if (coef == ans) 
    ans2 = min(ans2, cur);
  
  for (int i = 1; i <= last && cur <= n / pri[p] && cur * pri[p] <= n; i++) 
    cur *= pri[p];
    dfs(p + 1, cur, coef * ((i + 2) * (i + 1) / 2), i);
  


int main() 
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
  scanf("%lld", &n);
  dfs(0, 1, 1, 999);
  printf("%lld\\n%lld\\n", ans2, ans);
View Code

T3 先给出递推式,不过面对如此大的数据范围递推也没办法,正解是真的神仙,几个位运算判断一波就搞了,%%%%%

std:

技术图片
#include <bits/stdc++.h>
using namespace std;
int n;
long long f0, f1;
int main() 
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
  scanf("%d", &n);
  int tg = 0;
  for (int i = 30; ~i; i--) 
    if (tg) 
      if ((n >> i) & 1) 
        f0 = f0 * 3 + f1 * 2 + 1;
       else 
        f0 = f0 * 3 + 1;
        f1 = f1 * 2;
      
     else if ((n >> i) & 1) 
      tg = 1;
      f1++;
    
  
  printf("%lld\\n", (f0 + f1) * 2 + 1);
View Code

%%%%% deco&sxk dalao 300pts AK

 

以上是关于暑假7.29 Test的主要内容,如果未能解决你的问题,请参考以下文章

暑假集训test-8-29

暑假集训test-8-30

大一暑假第五周周进度总结报告

暑假都有哪些精彩的活动

世界上最遥远的距离莫过于:「暑假前」和「暑假后」

2021软件创新实验室暑假集训总结篇