2022.8.10 精弘热身赛

 

全部更新完毕,开摆!

 

紧张刺激的热身赛

(比赛前倒了咖啡都妹有喝)

i和l其实都不该是一点代码都写不出来的程度,复健前路漫长(有没有一种可能,能复健到的上限本来就很低)

希望晚上能把剩下两个搞出来(搞出来力!)

 

 

A:

hello,world!

太紧张了,紧张到连个引号都差点不会打

1 #include<bits/stdc++.h>
2 #define ll long long
3 using namespace std;
4 int main()
5 {
6     cout<<'"'<<"Welcome to Jinghong Union."<<'"'<<endl;
7     return 0;
8 }
A

 

 

B:

太紧张了,紧张到连个strlen都差点不会用

#include<bits/stdc++.h>
#define ll long long
using namespace std;
char s[110];
int main()
{
    scanf("%s",s+1);
    int len=strlen(s+1);
    printf("%c%d%c\n",s[1],len-2,s[len]);
    return 0;
}
B

 

 

C:

太紧张了,紧张到连个循环都差点不会写

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int n,a,num;
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     a=n;
 9     while(a){
10         num+=a%10;
11         a/=10;
12     }
13     if(n%num==0)printf("Yes\n");
14     else printf("No\n");
15     return 0;
16 }
C

 

 

D:

发现已经有大佬在唰唰ac,不紧张了

循环三个数显然是超时的,所以循环两个判断最后一个

(忘了判断z<=k还wa了几次,丢人)

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int k,s,z;
 5 long long ans;
 6 int main()
 7 {
 8     scanf("%d%d",&k,&s);
 9     for(int i=0;i<=min(k,s);i++){
10         for(int j=0;j<=min(k,s);j++){
11             z=s-j-i;
12             if(z>=0&&z<=k)ans++;
13         }
14     }
15     printf("%lld\n",ans);
16     return 0;
17 }
D

 

 

E:

数据范围很小啊,太好了,直接对每个点暴力枚举八个方向

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int h,w;
 4 int hh[10]={0,-1,-1,-1,0,0,1,1,1};
 5 int ll[10]={0,-1,0,1,-1,1,-1,0,1};
 6 char a[55][55];
 7 int work(int x,int y){
 8     int ans=0;
 9     for(int i=1;i<=8;i++){
10         if(a[x+hh[i]][y+ll[i]]=='#')ans++;
11     }
12     return ans;
13 }
14 int main()
15 {
16     scanf("%d%d",&h,&w);
17     for(int i=1;i<=h;i++){
18         getchar();
19         for(int j=1;j<=w;j++){
20             scanf("%c",&a[i][j]);
21         }
22     }
23     for(int i=1;i<=h;i++){
24         for(int j=1;j<=w;j++){
25             if(a[i][j]=='#')printf("%c",a[i][j]);
26             else printf("%d",work(i,j));
27         }
28         printf("\n");
29     }
30     return 0;
31 }
E

 

 

F:

模拟过程发现是尾放一个头放一个如此循环,所以开两个变量模拟头尾指针,然后按顺序输出

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int n,head,tail,tag,cnt;
 5 int a[200010],b[200010];
 6 int main()
 7 {
 8     scanf("%d",&n);
 9     head=1,tail=cnt=n;
10     for(int i=1;i<=n;i++){
11         scanf("%d",&a[i]);
12     }
13     while(head<=tail){
14         if(!tag){
15             b[head]=a[cnt];
16             head++;
17         }
18         else{
19             b[tail]=a[cnt];    
20             tail--;
21         }
22         tag^=1;
23         cnt--;
24     }
25     for(int i=1;i<=n;i++){
26         printf("%d ",b[i]);
27     }
28     return 0;
29 }
F

 

 

G:

暴力递归了,乱算了一下复杂度应该不会超过nlogn

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 char s[100010];
 5 int len;
 6 int work(int l,int r,int n){
 7     if(l==r)return 1;
 8     int a=n/2;
 9     for(int i=1;i<=a;i++){
10         if(s[l+i-1]!=s[r-i+1])return 0;
11     }
12     return 1+(work(l,l+a-1,a)&work(r-a+1,r,a));
13 }
14 int main()
15 {
16     scanf("%s",s+1);
17     len=strlen(s+1);
18     printf("%d\n",work(1,len,len));
19     return 0;
20 }
G

 

 

H:

因为数组越界而wa了11次的题(丢人)

再处理到N我就是……

筛出上限的素数,然后进行一个前缀和

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=5000010;
 4 long long l,k,t;
 5 long long dd,vis[N],ee,a[N],cnt,b[N],aa,bb,cc;
 6 void work(long long x){
 7     for(long long i=2;i<=x;i++){
 8         if(!vis[i]){
 9             a[++cnt]=i;
10         }
11         for(long long j=1;j<=cnt&&i*a[j]<=x;j++){
12             vis[i*a[j]]=1;
13             if(i%a[j]==0)break;
14         }
15     }
16     for(long long i=2;i<=x;i++){
17         b[i]=b[i-1]+(vis[i]?0:1);
18     }
19 }
20 int main()
21 {
22 //    freopen("1.txt","r",stdin);
23 //    freopen("1.out","w",stdout);
24     scanf("%lld",&t);
25     work(N-10);
26     while(t--){
27         scanf("%lld%lld",&l,&k);
28         long long ans=b[l+k*2-1]-b[l-1];
29         if(ans>k)printf("Yes\n");
30         else printf("No\n");
31     //    printf("%lld\n",ans);
32     }
33     return 0;
34 }
H

 

简单规律可知……(根本没想到)

从l到l+2k,因为所有偶数除了2都不是质数,所有最多只有k个质数

要满足yes肯定要包括2,特判一下

我怎么没想到呢,我是呆逼

1 #include<stdio.h>
2 int t,l,k;
3 int main(){
4     scanf("%d",&t);
5     while(t--){
6         scanf("%d%d",&l,&k);
7         puts(l==2&&k<=3?"Yes":"No");
8     }
9 }
H(脑洞版)

 

 

I:

考场上怎么就没想到呢,明明大致思路都有了

s<=2000,枚举要分成多少个数字

因为每个数字要>2,就对s减去要分成的块数*2,让每个数字变成>0

然后用挡板法/插板法,c[s-i*2-1][i-1]

到底为什么没想出来呢,为什么呢(致可恶的数组越界吃掉的一个小时)

不能提交了所以拿别人的正解对了个拍,大致看了下大佬的过程好像不一样,等下进行一个细读

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int mod=1e9+7;
 4 int s;
 5 long long ans,c[2010][2010];
 6 void work(){
 7     c[0][0]=c[1][1]=c[1][0]=1;
 8     for(int i=2;i<=s;i++){
 9         c[i][0]=1;
10         for(int j=1;j<=i;j++){
11             c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
12         }
13     }
14     for(int i=2;i<=s;i++){
15         c[1][i]=1;
16     }
17 }
18 int main()
19 {
20     scanf("%d",&s);
21     work();
22     for(int i=1;i<=s/3;i++){
23         ans=(ans+c[s-i*2-1][i-1])%mod;
24     }
25     printf("%lld\n",ans);
26     return 0;
27 }
I

 大致读懂了,dp转移方程a[i]=a[i-1]+a[i-3],a为i数值时的方案数

3是增加新数字的最低限度,4的话可以由之前的3得到,从i-1转移就是给每种方案的最后一个数字+1,然后要新增一个数字3那就是从i-3转移

 

 

J:

朴素的数学题感和简单规律可知,首先选最大的一个做x肯定比任何一个小于它的好,然后y最好最接近它的二分之一

判断离n/2最近可能在n为奇数时出问题,所以对于奇数再加一个n/2+1

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,a[100010],ans;
 4 long long maxx=1e18;
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     for(int i=1;i<=n;i++){
 9         scanf("%d",&a[i]);
10     }
11     sort(a+1,a+n+1);
12     int b=a[n]/2,c=(a[n]%2?a[n]/2+1:a[n]/2);
13     for(int i=1;i<=n;i++){
14         if(max(b-a[i],a[i]-b)+max(c-a[i],a[i]-c)<maxx){
15             maxx=max(b-a[i],a[i]-b)+max(c-a[i],a[i]-c);
16             ans=a[i];
17         }
18     }
19     printf("%d %d\n",a[n],ans);
20     return 0;
21 }
J

 

 

K:

题目等价于:求每个值能对多少区间有贡献(为多少区间的最小值),然后求和

用栈来求每个值作为最小值所在的范围,求它能管辖的左右端点

从左往右挨个入栈,如果当前栈顶的值大于要加入的值,那么就说明栈顶这个值管辖的范围到此为止了,接下来是新数字的time

如果当前栈顶的值小于要加入的值,那么它的管辖范围不被新值影响,继续呆在栈里

加完所有数字以后还在栈里的,它的右端点就是n

左端点同理

然后对于a[i],它会对(i-l+1)*(r-i+1)个区间有贡献,乘一下然后所有i求和

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=2e5+10;
 4 int n;
 5 int a[N],st[N],top;
 6 long long ans,l[N],r[N];
 7 int main()
 8 {
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++){
11         scanf("%d",&a[i]);
12     }
13     for(int i=1;i<=n;i++){
14         while(top&&a[st[top]]>a[i]){
15             r[st[top]]=i-1;
16             top--;
17         }
18         st[++top]=i;
19     }
20     while(top){
21         r[st[top]]=n;
22         top--;
23     }
24     for(int i=n;i>=1;i--){
25         while(top&&a[st[top]]>a[i]){
26             l[st[top]]=i+1;
27             top--;
28         }
29         st[++top]=i;
30     }
31     while(top){
32         l[st[top]]=1;
33         top--;
34     }
35     for(int i=1;i<=n;i++){
36         ans+=(i-l[i]+1)*(r[i]-i+1)*a[i];
37     }
38     printf("%lld\n",ans);
39     return 0;
40 }
K

 

 

L:

在大神的指点下领悟了:

异或和相当于二进制不进位加法,所以题目要求异或和等于数值加和,相当于二进制状态下加和不进位,也就是同一有效区间内所有数在同一位二进制上没有重复的1,整个区间内所有数在同一个二进制位上总共只有不多于一个1

那么就维护这个有效区间,从左到右加入数字。如果这个数字加入区间以后满足上述条件,那就更新维护数组。如果不满足,那就从左端点开始移除数字,同时判断现在的左端点是否满足条件,不断更新。

每次的新数字就是新的右端点,持续统计一下每个右端点对应的区间数量,输出总和。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=2e5+10;
 5 int n,ans,l,r;
 6 int a[N],b[N][25],c[25];
 7 int check(int x){
 8     for(int i=0;i<=20;i++){
 9         if(b[x][i]&c[i])return 1;
10     }
11     return 0;
12 }
13 int main()
14 {
15     scanf("%d",&n);
16     for(int i=1,x;i<=n;i++){
17         scanf("%d",&a[i]);
18         x=a[i];
19         for(int j=0;j<=20;j++){
20             b[i][j]=x&1;
21             x>>=1;
22         }
23     }
24     l=1;
25     for(int i=1;i<=n;i++){
26         while(check(i)&&l<=r){
27             for(int j=0;j<=20;j++){
28                 if(b[l][j])c[j]=0;
29             }
30             l++;
31         }
32         for(int j=0;j<=20;j++){
33             c[j]|=b[i][j];
34         }
35         r=i;
36         ans+=r-l+1;
37     }
38     printf("%d\n",ans);
39     return 0;
40 }
L

 

 

 

 

 

 

 

posted @ 2022-08-10 17:19  Chloris_Black  阅读(155)  评论(0编辑  收藏  举报