“思特奇杯”编程之星初赛——十一届蓝桥杯大赛省赛第二场C/C++大学B组

门牌制作

题面

代码

#include<iostream>
using namespace std;
int main()
{
	int ans=0;
	for(int i=1;i<=2020;i++)
	{
		int j=i;
		while(j!=0)
		{
			if(j%10==2)
			ans++;
			j=j/10;
		}
	}
	cout<<ans<<endl;
	return 0;
 } 

结果

624

既约分数

题面

在这里插入图片描述

代码

#include<iostream>
#include<algorithm> 
using namespace std;
int main()
{
	int ans=0;
	for(int i=1;i<=2020;i++)
	{
		for(int j=1;j<=2020;j++)
		{
			if(__gcd(i,j)==1)
		    ans++;
	    }
    } 
    cout<<ans<<endl;
    return 0;
 } 

结果

2481215

蛇形填数

题面

在这里插入图片描述

暴力枚举法

在模拟整个过程中,发现了一些规律,假设在同一斜线上的数为一组数,则一行一列的数在第一斜线,二行二列的数在第三斜线,三行三列的数在第五斜线,由此可以推出20行20列的数在第三十九斜线。而我们又可以观察出n行n列的数都在斜线的正中间,因此我们可以很快的算出1+2+3+……+38+39=780.
这一列有39个数,而正中间的数则为761

代码

#include<bits/stdc++.h>
using namespace std;
int a[50][50];
int main(){
	/*
	这里分奇数偶数情况讨论 	
	
	*/ 
	int id=0;//要填的数 
	for(int i=1;i<=40;i++){
		for(int j=0;j<i;j++)  //斜着填
		{
		  if(i&1){   //奇数
		  a[i-j][j+1]=++id;	  
		} 
		  else{
		  a[j+1][i-j]=++id;	
		} 
	}
}
	      cout<<a[20][20]<<endl; 
	return 0;
} 

结果

761

跑步锻炼

题面

在这里插入图片描述

代码

#include <iostream>
using namespace std;
int M[13] = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int main() {
  int y = 2000, m = 1, d = 1, w = 6, ans = 2;
  while (y != 2020 || m != 10 || d != 1) {
    if (y % 400 == 0 || (y % 4 == 0 && y % 100)) {
      M[2] = 29;
    } else {
      M[2] = 28;
    }
    d++;
    w = (w + 1) % 7;
    if (d > M[m]) {
      d = 1;
      m++;
      if (m > 12) {
        m = 1;
        y++;
      }
    }
    if (d == 1 || w == 1) {
      ans++;
    }
    ans++;
  }
  cout << ans << endl;
  return 0;
}

结果

8879

七段码

题面

在这里插入图片描述

暴力枚举法

我是在经过罗列出所有的可能情况,最终发现:在一个二极管发光的情况有7种情况,两个二极管发光的情况有10种(ab,af,bc,bg,cg,cd,de,eg,ef,fg),三个二极管发光的情况有16种(abf,abc,abg,afg,afe,bcd,bcg,bgf,bge,cgd,cgf,cge,cde,deg,def,efg),四个二极管发光的情况有20种(abcd,abcg,abcf,abge,abgf,abfe,afeg,bcde,bcdg,bcgf,bcge,bged,bgef,cdef,cdeg,cdgf,cgfa,cgfe,defg,defa),五个二极管发光的情况有19种,在七个里面任选5个是21种情况,排除(agced,afgbd)两种,剩下19种,六个二极管发光的情况有7种(一个发光),七个二极管发光的情况有1种。
因此,加起来可知结果为80种。

代码

#include<iostream>
#include<cstring>
using namespace std;
int fa[10];
bool vis[10];
// a -> 0    b -> 1   c -> 2
// d -> 3    e -> 4   f -> 5   g -> 6 
int ans;
int get(int cur){
	if(cur == fa[cur]) return cur;
	return get(fa[cur]);
}

void merge(int cx,int cy){
	int xx = get(cx);
	int yy = get(cy);
	
	fa[xx] = yy;
}
int main(){
	
	for(int st = 1;st < (1<<7);st ++){
		
		memset(vis,false,sizeof(vis));
		
		for(int i = 0;i <= 6;i ++) fa[i] = i;
		
		
		for(int i = 0;i <= 6;i ++){ //这里的从 0 开始计数也很巧,因为第一次是1左移0位 
			if(st & (1<<i)){
				vis[i] = true;
				if(i == 0){
					if(vis[1]) merge(0,1);
					if(vis[5]) merge(0,5);
				}
				
				if(i == 1){
					if(vis[0]) merge(1,0);
					if(vis[6]) merge(1,6);
					if(vis[2]) merge(1,2);
				}
				
				if(i == 2){
					if(vis[1]) merge(2,1);
					if(vis[3]) merge(2,3);
					if(vis[6]) merge(2,6);
				}
				
				if(i == 3){
					if(vis[2]) merge(3,2);
					if(vis[4]) merge(3,4);
				}
				
				if(i == 4){
					if(vis[3]) merge(4,3);
					if(vis[5]) merge(4,5);
					if(vis[6]) merge(4,6);
				}
				
				if(i == 5){
					if(vis[0]) merge(5,0);
					if(vis[4]) merge(5,4);
					if(vis[6]) merge(5,6);
				}
				
				if(i == 6){
					if(vis[1]) merge(6,1);
					if(vis[2]) merge(6,2);
					if(vis[4]) merge(6,4);
					if(vis[5]) merge(6,5);
				}
			}
			
			
		}
		// 判断是否是一个连通块
		int cnt = 0;
		for(int i = 0;i <= 6;i ++){
			if(vis[i] && (i == fa[i])){
				cnt ++;
			}
		}
		
		if(cnt == 1) ans ++; 
	}
	
	cout << ans;
	return 0;
}

DFS求联通块代码

#include <bits/stdc++.h>
using namespace std;
const int N = 10;
char a[N][N];
int n, m, vis[N][N];

void dfs(int r, int c, int f) {
  if (r < 0 || r >= m || c < 0 || c >= n) {
    return;
  }
  if (vis[r][c] > 0 || a[r][c] != '1') {
    return;
  }
  vis[r][c] = f;
  for (int i = -1; i <= 1; i++){
    for (int j = -1; j <= 1; j++){
      if (i != 0 || j != 0){
        dfs(r + i, c + j, f);
      }
    }
  }
}

int main() {
  int sum = 0;
  freopen("in.txt", "r", stdin);
  while (~scanf("%d%d", &m, &n)) {
    for (int i = 0; i < m; i++){
      scanf("%s", a[i]);
    }
    memset(vis, 0, sizeof(vis));
    int cnt = 0;
    for (int i = 0; i < m; i++){
      for (int j = 0; j < n; j++){
        if (vis[i][j] == 0 && a[i][j] == '1'){
          dfs(i, j, ++cnt);
        }
      }
    }
    if (cnt == 1){
      sum += 1;
    }
  }
  printf("%d\n", sum);
  return 0;
}


结果

80

成绩统计

题面

在这里插入图片描述

代码

#include<iostream>
using namespace std;
int main()
{
	int n,x;
	int i=0,j=0; 
	cin>>n;
	int f=n;
	while(f!=0)
	{
	    cin>>x;
	    if(x>=60)
	    {
	    	i++;
		}
		if(x>=85)
		{
			j++;
		}
		f--;
	}
	double hege=i*1.0/n*1.0;
	double youxiu=j*1.0/n*1.0;
	int ans1=int(hege*1000+5)/10;
	int ans2=int(youxiu*1000+5)/10;
	cout<<ans1<<"%"<<endl;
	cout<<ans2<<"%"<<endl;
	return 0; 
 } 

回文日期

题面

在这里插入图片描述

代码

#include <cstdio>
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
using namespace std;

int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool hf(int n){
	int yy = n / 10000;
	int mm = n % 10000 / 100;
	int dd = n % 100;
	if(mm > 12) return false;
	if((yy%4==0 && yy%100!=0) || yy%400==0){
		day[2] = 29;
	}else{
		day[2] = 28;
	}
	if(dd > day[mm]) return false;
	return true;
}

bool rev(int n){
	stringstream ss;
	ss << n;
	string s = ss.str();
	string t = s;
	reverse(s.begin(), s.end());
	if(t == s) return true;
	return false;
}

int main(){
	int n;
	scanf("%d", &n);
	bool flag = 1;
	for(int i=n+1; i<1e8; i++){
		if(hf(i)){
			if(rev(i) && flag){
				printf("%d\n", i);
				flag = 0;
			}
			if(rev(i)){
				stringstream ss2;
				ss2 << i;
				string s = ss2.str();
				if(s[0]==s[2] && s[0]==s[5] && s[0]==s[7]){
					if(s[1]==s[3] && s[1]==s[4] && s[1]==s[6]){
						printf("%d", i);
						break;
					}
				}
			}
		}
	}
	
	return 0;
}

子串分值和

题面

在这里插入图片描述

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
char s[N];
ll vis[40];
int main() {
  scanf("%s", s + 1);
  int n = strlen(s + 1);
  ll ans = 0;
  for (int i = 1; i <= n; i++) {
    ans += (i - vis[s[i] - 'a']) * (n - i + 1);
    vis[s[i] - 'a'] = i;
  }
  cout << ans << endl;
  return 0;
}

平面划分

题面

在这里插入图片描述

代码

#include<iostream>
#include<map>
#include<set>
using namespace std;
set<pair<double, double> > line;//存放直线信息
int n;
int ans = 1;
double x, y;
void compute(double a, double b) {
	double c, d;
	pair<double, double> inter;
	set<pair<double, double> > point;
	for (auto it : line) {
		c = it.first, d = it.second;
		if (c != a) {

			inter.first = (d - b) / (a - c);
			inter.second = a*inter.first + b;

			point.insert(inter);//存放新的直线与其余直线的交点
		}

	}
	ans += point.size();//每有一个点区域数量+1
	point.clear();
}
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> x >> y;
		int l = line.size();
		line.insert(make_pair(x, y));
		
		if (line.size() != l) {//重边不会影响平面数目
			ans++;//无论什么情况只要不是重边,加入新的直线后区域数量无条件+1
			compute(x, y);
		}
	}
	cout << ans;
	return 0;
}

字串排序

题面

在这里插入图片描述

代码

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 135, M = 10010;

int f[N][30][N];
//chcnt[i][j]记录第i个位置取字母j+'a'的逆序对最大值 
int chcnt[N][30];
//mlen[i]记录每个位置的最大值 
int mlen[N];

void dp()
{
	for (int i = 2; i < N; ++i)
	{
		int m = 0;
		for (int j = 1; j <= 'z' - 'a'; ++j)
		{
			for (int k = 1; k < i; ++k)
			{
				if (k > 1) f[i][j][k] = f[i - 1][j][k - 1] + i - k;
				else f[i][j][k] = chcnt[i - 1][j - 1] + i - 1;
				chcnt[i][j] = max(chcnt[i][j], f[i][j][k]);
			}
			m = max(m, chcnt[i][j]);
		}
		mlen[i] = m;
	}

}

int main()
{
	dp();

	int score = 0;
	cin >> score;
	//找出最短长度值
	int beg = 0;
	for (int i = 1; i < N; ++i)
		if (mlen[i] >= score)
		{
			beg = i;
			break;
		}

	int curr = 0;	//用于记录逆序值
	int same = 1;	//记录后缀中有多少个相同字母
	char last = 'z' + 1;//记录上一个字母是什么 
	for (int i = beg; i > 0; --i)
	{
		//从a开始枚举
		int j = 0;
		for (; j <= last - 'a'; ++j)
		{
			if (j == last - 'a') curr -= same;
			if (curr + chcnt[i][j] >= score)
			{
				curr += i - 1;
				break;
			}
		}
		if (j == last - 'a') same++;
		else
		{
			last = j + 'a';
			same = 1;
		}
		cout << last;
	}
	cout << endl;

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷糊小成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值