第十二届蓝桥杯C++ B组

A:计算256MB能够存放多少个int

1 int main()
2 {
3     cout<<256*1024*1024/4;
4     return 0;
5 }

ans=67108864

B:计算2021张1到10的卡片能够拼出1~n的最大的n

 1 int cnt[10];
 2 int main()
 3 {
 4     for(int i=0;i<10;i++) cnt[i]=2021;
 5     int k=1;
 6     while(1){
 7         int t=k;
 8         while(t) cnt[t%10]--,t/=10;
 9         for(int i=0;i<10;i++)
10             if(cnt[i]<0){
11                 cout<<k-1;
12                 return 0;
13             }
14         k++;
15     }
16     return 0;
17 }

ans=3181

C:给定一个20*21的棋盘,任选两点,问有多少条直线。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define x first
 6 #define y second
 7 using namespace std;
 8 typedef pair<double,double> PII;
 9 const double eps=1e-6;
10 struct node{
11     double k,b;
12     bool operator<(const node& t)const{
13         if(fabs(k-t.k)<eps) return b<t.b;
14         return k<t.k;
15     }
16 };
17 vector<node> v;
18 int main()
19 {
20     for(int x1=0;x1<20;x1++){
21         for(int y1=0;y1<21;y1++){
22             for(int x2=0;x2<20;x2++){
23                 for(int y2=0;y2<21;y2++){
24                     if(x1!=x2){
25                         double k=double(y2-y1) / (x2-x1);
26                         double b=y1-k*x1;
27                         v.push_back({k,b});
28                     }
29                 }
30             }
31         }
32     }
33     sort(v.begin(),v.end());
34     int res=1;
35     for(int i=1;i<v.size();i++){
36         if(fabs(v[i].k-v[i-1].k)>eps||fabs(v[i].b-v[i-1].b)>eps)
37             res++;
38     }
39     cout<<res+20;
40     return 0;
41 }

ans=40257

D:给定一个很大的数,问差分成3个数相乘有多少种方案,1*2*2和2*2*1是不同的方案。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 LL n=2021041820210418;
 7 vector<LL> p;
 8 int main()
 9 {
10     LL t=n;
11     for(LL i=1;i<=n/i;i++){
12         if(t%i==0){
13             p.push_back(i);
14             if(t/i!=i)
15                 p.push_back(t/i);
16         }
17     }
18     LL res=0;
19     for(int i=0;i<p.size();i++){
20         for(int j=0;j<p.size();j++){
21             for(int k=0;k<p.size();k++){
22                 if(p[i]*p[j]*p[k]==n){
23                     res++;
24                 }
25             }
26         }
27     }
28     cout<<res;
29     return 0;
30 }

ans=2430

E:裸的最短路问题。(当时用的floyd,因为好写)

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=2050;
 6 const int INF=0x3f3f3f3f;
 7 int f[N][N];
 8 int gcd(int a,int b){
 9     return b==0?a:gcd(b,a%b);
10 }
11 int main()
12 {
13     memset(f,0x3f,sizeof f);
14     for(int i=1;i<=2021;i++){
15         for(int j=1;j<=2021;j++){
16             if(abs(i-j)<=21){
17                 int tmp=i*j/gcd(i,j);
18                 f[i][j]=tmp;
19                 f[j][i]=tmp;
20             }
21         }
22     }
23     for(int k=1;k<=2021;k++){
24         for(int i=1;i<=2021;i++){
25             for(int j=1;j<=2021;j++){
26                 if(f[i][k]!=INF&&f[k][j]!=INF){
27                     f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
28                 }
29             }
30         }
31     }
32     cout<<f[1][2021];
33     return 0;
34 }

ans=10266837

F:时间显示

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 int main()
 6 {
 7     long long n;
 8     cin>>n;
 9     n/=1000;
10     n%=24*60*60;
11     int h=n/(60*60);
12     n%=60*60;
13     int m=n/60;
14     n%=60;
15     int s=n;
16     printf("%02d:%02d:%02d",h,m,s);
17     return 0;
18 }

G:背包问题,但是需要加上一个偏移量

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=110;
 6 const int M=2e5+10,B=M/2;
 7 int w[N];
 8 bool f[N][M];
 9 int main()
10 {
11     int n,m=0;
12     cin>>n;
13     for(int i=1;i<=n;i++) cin>>w[i],m+=w[i];
14     f[0][0+B]=1;
15     for(int i=1;i<=n;i++){
16         for(int j=-m;j<=m;j++){
17             f[i][j+B]=f[i-1][j+B];
18             if(j-w[i]>=-m) f[i][j+B]|=f[i-1][j-w[i]+B];
19             if(j+w[i]<=m) f[i][j+B]|=f[i-1][j+w[i]+B];
20         }
21     }
22     int res=0;
23     for(int i=1;i<=m;i++)
24         if(f[n][i+B])
25             res++;
26     cout<<res;
27     return 0;
28 }

H:杨辉三角形。

说实话挺复杂的,将杨辉三角形斜着看。

右半边可以直接不看了,因为右边的左边都有,所以一定更先出现。

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

1 6 15 20 15 6 1

越靠近中间列的增加的越快。

我们得先从中间开始找n,对于每一列找到大于等于n的最小的数,若他是n的话则他就是答案了。

否则找前面一列的,可以发现答案是必然存在的(看第二列)。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 LL n;
 7 LL C(LL a,LL b){
 8     LL res=1;
 9     for(int i=a,j=1;j<=b;i--,j++){
10         res=res*i/j;
11         if(res>n) return res;
12     }
13     return res;
14 }
15 bool check(LL k){
16     LL l=2*k,r=n;//左端点为第2*k行,右端点为第n行
17     while(l<r){
18         LL mid=l+r>>1;
19         if(C(mid,k)>=n) r=mid;
20         else l=mid+1;
21     }
22     if(C(r,k)!=n) return false;
23     cout<<r*(r+1)/2 + k+1;
24     return true;
25 }
26 int main()
27 {
28     cin>>n;
29     if(n==1){
30         cout<<1<<endl;
31         return 0;
32     }
33     for(int i=16;;i--){
34         if(check(i)){
35             break;
36         }
37     }
38     return 0;
39 }

I:非常复杂的一道题。

因为n,m<=1e5,若是直接排序n*m*logn,肯定会超时的。

可以通过栈来解这道题。

在翻转的过程中虚线部份就已经确定了。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define x first
 5 #define y second
 6 using namespace std;
 7 typedef pair<int, int> PII;
 8 const int N=1e5+10;
 9 PII stk[N];
10 int top=0;
11 int ans[N];
12 int main()
13 {
14     int n,m;
15     cin>>n>>m;
16     while(m--){
17         int p,q;
18         cin>>p>>q;
19         if(p==0){
20             while(top&&stk[top].x==0) q=max(q,stk[top--].y);
21             while(top>=2&&q>=stk[top-1].y) top-=2;
22             stk[++top]={0,q};
23         }else if(top){
24             while(top&&stk[top].x==1) q=min(q,stk[top--].y);
25             while(top>=2&&q<=stk[top-1].y) top-=2;
26             stk[++top]={1,q};
27         }
28     }
29     //以上是找出正确的操作。
30     int k=n,l=1,r=n;
31     for(int i=1;i<=top;i++){
32         if(stk[i].x==0){
33             while(r>stk[i].y&&l<=r) ans[r--]=k--;
34         }else if(stk[i].x==1){
35             while(l<stk[i].y&&l<=r) ans[l++]=k--;
36         }
37         if(l>r) break;
38     }
39     if(top%2)//若是没放完的话
40         while(l<=r) ans[l++]=k--;
41     else 
42         while(l<=r) ans[r--]=k--;
43     for(int i=1;i<=n;i++)
44         cout<<ans[i]<<" ";
45     return 0;
46 }

J:巨难的一道题。

1、括号序列合法的充要条件:左括号和右括号数目相等,且任意前缀左括号数目>=右括号数目
2、向不合法的括号序列中添加括号能否单独考虑左右括号?
  可以,因为若是不存在左括号和右括号放在同一个空隙里的话,必然是可以的。
       若是存在左括号与右括号放到同一个空隙里的话只有可能是" ))))((( "这种情况。
3、此时可以单独考虑左括号,那么如何保证考虑左括号的时候不会有重复的情况?
  比如 ) ) 能够添加成 ( ( ) ) ,但是这会有两种解释一是在0前面添加两个左括号,或者在0前面以及1前面各添加一个左括号。
  可以发现右括号将整个序列分成了3个左括号段,一个括号序列被每一段左括号的数目唯一确定。我们固定只能在) 前面添加(。
4、计算向序列中添加左括号的方案数。
  DP。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const int N=5010,mod=1e9+7;
 7 char str[N];
 8 LL f[N][N];
 9 LL n;
10 LL calc(){
11     memset(f,0,sizeof f);
12     f[0][0]=1;
13     for(int i=1;i<=n;i++){
14         if(str[i]=='('){
15             for(int j=1;j<=n;j++)
16                 f[i][j]=f[i-1][j-1];
17         }else if(str[i]=')'){
18             f[i][0]=(f[i-1][0]+f[i-1][1])%mod;
19             for(int j=1;j<=n;j++)
20                 f[i][j]=(f[i-1][j+1]+f[i][j-1])%mod;
21         }
22     }
23     for(int i=0;i<=n;i++){
24         if(f[n][i])
25             return f[n][i];
26     }
27     return -1;
28 }
29 int main()
30 {
31     cin>>str+1;
32     n=strlen(str+1);
33     LL l=calc();
34     reverse(str+1,str+1+n);
35     for(int i=1;i<=n;i++)
36         if(str[i]=='(') str[i]=')';
37         else str[i]='(';
38     LL r=calc();
39     cout<<l*r%mod;
40     return 0;
41 }
原文地址:https://www.cnblogs.com/greenofyu/p/14736794.html