第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第1张图片
签到题:答案624

#include
using namespace std;
int sum;
void jisuan(int x){
	while(x){
		if(x%10==2) sum++;
		x/=10;
	}
}
int main()
{
	for(int i=1;i<=2020;i++) jisuan(i);
	cout<<sum<<endl;
	return 0;
}

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第2张图片
答案:2481215
暴力枚举分子分母即可。

#include
using namespace std;
int sum=0;
int gcd(int x,int y){
	if(x%y==0) return y;
	return gcd(y,x%y);
}
int main()
{
	for(int i=1;i<=2020;i++)
	for(int j=1;j<=2020;j++)
	if(gcd(i,j)==1) sum++;
	cout<<sum<<endl;
	return 0;
}

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第3张图片
答案:761
解析:找规律题,不难发现对角线上的数字个数是一个1-n的等差数列,且第n行m列的数所在对角线上有n+m-1个数字,对角线上的数字为奇数时蛇形矩阵方向向上;n(n+1)/2+x
第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第4张图片
答案:8879
总的天数+月初且不是周一的天数+周一的天数

#include
using namespace std;
int sum=0,s=0;
int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
	for(int i=2000;i<2020;i++){
		if(i%4==0&&i%100!=0||i%400==0) month[2]++;
			for(int i=1;i<=12;i++){
				if((sum+6)%7!=1) s++;//计算是月初且不是周一的日子 
				sum+=month[i];
				
			}
			if(month[2]==29) month[2]--;
	}
	month[2]++;
	for(int i=1;i<=9;i++){ //2020年的前9个月 
			sum+=month[i];
			if((sum+6)%7!=1) s++;
	}
	sum+=2;//加上2020.10.1日
	int z=sum+s+(sum-2+6)/7;
	cout<<z<<endl;
	return 0; 
}

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第5张图片
答案:80
7!种组合
暴搜每种组合,然后使用并查集或者搜索判断是否在一个连通块

#include
#include 
#include
#include
using namespace std;
const int N=2222223;
int h[N],e[N],ne[N],idx;  //领接表 
bool st[N];    //标记该二极管是否已亮 
int sum;
vector<int>g;   //记录不同组合二极管管的映射之和 
void add(int a,int b){       //插入连通点 
	e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void dfs(int a){
        
     sum+=a;
     st[a]=true;
    g.push_back(sum);
     
	for(int i=h[a];i!=-1;i=ne[i]){  //遍历当前二极管所有的相邻二极管 
		int j=e[i];
		if(!st[j]) {    //判断当前二极管是否已经打开 
			dfs(j);
			sum-=j;     //回溯 
			st[j]=false;
		}
	}
  st[a]=false;
}
int main()
{
	//a  b  c   d     e     f       g
	//2 22 222 2222 22222 222222 2222222   //映射确保每种组合之和都不同 
	memset(h,-1,sizeof h);    //领接表初始化 
	add(2,22);add(22,2);
	add(2,222222);add(222222,2);
	add(22,222);add(222,22);
	add(22,2222222);add(2222222,22);
	add(222,2222);add(2222,222);
	add(222,2222222);add(2222222,222);
	add(2222,22222);add(22222,2222);
	add(22222,222222);add(222222,22222);
	add(22222,2222222);add(2222222,22222);
	add(222222,2222222);add(2222222,222222);
	

	dfs(2);   //以不同二极管为起点搜索 
	sum=0;
	dfs(22);
	sum=0;
	dfs(222);
	sum=0;
	dfs(2222);
	sum=0;
	dfs(22222);
	sum=0;
	dfs(222222);
	sum=0;
	dfs(2222222);
	
	int res=0;
	sort(g.begin(),g.end());
	for(int i=0;i<g.size();i++)   //有多少种不同结果就有多少种组合 
	if(i==0||g[i]!=g[i-1]) res++;
	 
	
	cout<<res<<endl;
	return 0;
}
 

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第6张图片

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第7张图片

#include
using namespace std;
int main()
{
	double n;
	cin>>n; 
	double jg=0,yx=0;
	int x;
	int s=n;
	while(s--){
		cin>>x;
		if(x>=60) jg++;
		if(x>=85) yx++;
	}
	int j=((jg/n+0.005)*100),y=((yx/n+0.005)*100);
	cout<<j<<"%\n"<<y<<"%";
	return 0;
}

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第8张图片
关键在于判断月份在1-12之间,天数不能越界

**关键在于判断月份在1-12之间,天数不能越界**
#include
using namespace std;
int a;
int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
	cin>>a;
	a=a/10000;
     for(int i=a+1;;i++){
       if(i%4==0&&i%100!=0||i%400==0) month[2]++;
     	int month1=(i%10)*10+(i/10)%10,day1=((i/100)%10)*10+i/1000;
		if(month[month1]>=day1&&month1>0&&month1<=12) {
			int year=i*10000+month1*100+day1;
			cout<<year<<endl;
			break;
		}
		if(month[2]==29) month[2]--;
	 }
	for(int i=a+1;;i++){
		if(i/100!=i%100) continue;
		if(i%4==0&&i%100!=0||i%400==0) month[2]++;
     	int month1=(i%10)*10+(i/10)%10,day1=((i/100)%10)*10+i/1000;
		if(month[month1]>=day1&&month1>0&&month1<=12) {
			int year=i*10000+month1*100+day1;
			cout<<year<<endl;
			break;
		}
		if(month[2]==29) month[2]--;
	}
	return 0; 
	
}

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第9张图片
第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第10张图片
方法一:二进制转换(能过60%)
依次枚举子串长度,并记录每个子串的不同字符个数;
1.如果(a[l][r-1]>>g[r])&1)即f[l][r-1]中已经存在g[r]; f[l][r]=f[l][r-1],a[l][r]=a[l][r-1];
2.否则 f[l][r]=f[l][r-1]+1,a[l][r]=a[l][r-1]+1<

s[N]为目标字符串
f[l][r]表示l~r之间不同字符个数
a[l][r]表示一个二进制数,1的个数和位置代表不同字符的个数和种类
g[i]表示第i为字符代表的数字g[i]=s[i]-‘a’

#include
#include
#include
using namespace std;
const int N=10010;

/*依次枚举子串长度,并记录每个子串的不同字符个数;
1.如果((a[l][r-1]>>g[r])&1),则f[l][r-1]中已经存在g[r]; f[l][r]=f[l][r-1],a[l][r]=a[l][r-1];
2.否则 f[l][r]=f[l][r-1]+1,a[l][r]=a[l][r-1]+1<
//s[N]为目标字符串
//f[l][r]表示l~r之间不同字符个数
//a[l][r]表示一个二进制数,1的个数和位置代表不同字符的个数和种类
//g[i]表示第i为字符代表的数字g[i]=s[i]-'a'
int f[N][N],a[N][N],g[N];
char s[N];

int main()
{
    scanf("%s",s+1);
    int n=strlen(s+1);
    for(int i=1;i<=n;i++) g[i]=s[i]-'a';
    
   long long int res=0;
    for(int len=1;len<=n;len++)
    for(int i=1;i+len-1<=n;i++){
       int l=i,r=i+len-1;
       if(l==r) f[l][r]=1,a[l][r]=1<<g[r];
       else {
        if((a[l][r-1]>>g[r])&1) f[l][r]=f[l][r-1],a[l][r]=a[l][r-1];
        else f[l][r]=f[l][r-1]+1,a[l][r]=a[l][r-1]+(1<<g[r]);
        }
        res+=f[l][r];
    }

    cout<<res<<endl;
    return 0;
}

方法二:计算字符贡献值(过100%)
举例:

ababc

i=1时,以当前字符为首字符的子串有(n-i+1)个分别为(a,ab,aba,abab,ababc),last[goal[i]]=i;
i=2时,以当前字符为首字符的子串有(n-i+1)个(b,ba,bab,babc),如果以i之前的点为起点包含i字符也同样有(n-i+1)个,总数应该为i*(n-i+1)
last[goal[i]]表示的是当前字符上一次出现的位置
i=3时,以当前字符为首字符的子串有(n-i+1)个(a,ab,abc),以i=2结尾也是(ba,bab,babc),以i=1有(aba,abab,ababc)这就和i=1时重复计算了两次a,所以总数是(i-last[goal[i]])*(n-i+1)

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

using namespace std;

const int N=100010;


char s[N];  //目标串 
int goal[N]; //将26个小写字母映射到0~25 
int last[26];  //记录最近一次字符出现的位置 

int main()
{
	cin>>s+1;
	int n=strlen(s+1);
	for(int i=1;i<=n;i++) goal[i]=s[i]-'a';
	
	long long int res=0;
	for(int i=1;i<=n;i++)
	{
		res+=1ll*(i-last[goal[i]])*(n-i+1);  
		last[goal[i]]=i;
	}
	cout<<res<<endl;
	return 0;
 } 

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第11张图片
这道题的规律是每加入一条直线与其他直线有k个交点,即多产生k+1个区域(仅供参考)

#include
#include
#include
#include
using namespace std;
int n;
//这道题的规律是每加入一条直线与其他直线有k个交点,即多产生k+1个区域 
struct point{
	int i,j;
/*	bool operator <(const point& t) const 
    {
        if(i!=t.i) return i 
}p[1010];
int main()
{
	cin>>n;
	for(int i=0;i<n;i++) scanf("%d%d",&p[i].i,&p[i].j);
//	sort(p,p+n);
	int sum=2;
	for(int i=1;i<n;i++){
		sum++;
		map<int,int>q;//存储当前直线与前面的直线的交点 
		for(int j=0;j<i;j++)
			if(p[j].i!=p[i].i){
				int x=(p[j].j-p[i].j)/(p[i].i-p[j].i);//x=(b1-b2)/(a2-a1) 
				int y=p[i].i*x+p[i].j+1;    //+1是为了特判y==0的情况 
			//	cout<
			//	cout<
				if(q[x]!=y) sum++;         //出现新的交点即++ 
				q[x]=y;                    //存储当前交点 
			}
	}
	cout<<sum<<endl;
	return 0; 
}

第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第12张图片
第十一届蓝桥杯大赛软件类省赛第二场C/C++大学B组(10月17日)_第13张图片
目前还没有思路(太菜了!!!)

你可能感兴趣的:(蓝桥杯)