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 }
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; }
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 }
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 }
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 }
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 }
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 }
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 }
简单规律可知……(根本没想到)
从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 }
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 }
大致读懂了,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 }
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 }
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 }