2021牛客暑期多校训练营1
这一场,题目好多都还不会,sg函数,FFT,DFT啥的都还不会。
B
几何题,给问球是否会掉下,不会球在什么位置
代码:
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
typedef long long ll;
int main()
{
//freopen("in.txt","r",stdin);
double r,a,b,h,o,x,y,z;
scanf("%lf%lf%lf%lf",&r,&a,&b,&h);
if(2*r<=b) printf("Drop\n");
else
{
printf("Stuck\n");
o=atan(2*h/(a-b));
x=tan(o/2)*r;
y=x-b/2;
z=y*tan(o);
printf("%.10lf\n",z+r);
}
return 0;
}D
给一个01矩阵,给你一个只有2的串,问可以放在01矩阵中0的地方,必须是连续放,不能拆。
思路就是在没一行检查有多少个子串,可以用KMP
代码:
#include <bits/stdc++.h>
using namespace std;
void getnext(string a,int next[])
{
int i=0,j=-1;
next[0]=-1;
while(i<a.size())
{
if(j==-1||a[j]==a[i])
{
i++;j++;next[i]=j;
}
else
j=next[j];
}
}
int kmp(string a,string b,int next[])
{
int i=0,j=0,ans=0;
while(a[i])
{
if(a[i]==b[j]||j==-1)
{i++;j++;}
else
{j=next[j];}
if(j==b.size())
{ans++;}
}
return ans;
}
int main(){
int n,m;
string a[2005];
string b,c;
int next[2005];
while(cin>>n>>m){
int ans=0;
for(int i=0;i<n;i++)
cin>>a[i];
cin>>b;
for(int i=0;i<m;i++){
b[i]-=2;
}
getnext(b,next);
for(int i=0;i<n;i++){
ans+=kmp(a[i],b,next);
}
/* for(int i=0;i<n;i++){
cout<<next[i]<<endl;
}*/
/* cout<<b<<endl;
cout<<kmp(a[0],b,next)<<endl;*/
cout<<ans<<endl;
}
}F
定义friendly数:连续子串是3的倍数就为friendl,0也算。
问L~R区间,有多少个friendly数,
不是数位DP!!!
枚举之后发现100以后的三位数都是friendly。所以打表
100以前只有这些是unfriendly;
1,4,7, 2,5,8, 11,14,17, 22,25,28, 41,44,47, 52,55,58, 71,74,77,
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[100]={1,1,1,2,2,2,3,3,3,4,5,5,6,7,7,8,9,9,10,11,12,13,13,14,15,15,16,17,17,18,19,20,21,22,23,24,25,26,27,28,29,29,30,31,31,32,33,33,34,35,36,37,37,38,39,39,40,41,41,42,43,44,45,46,47,48,49,50,51,52,53,53,54,55,55,56,57,57,58,59,60,61,61,62,63,63,64,65,65,66,67,68,69,70,71,72,73,74,75,76};
ll cou(ll x)
{
if(x<0)return 0;
else {
if(x<100)return dp[x];
else{
ll y=x-99+76;
return y;
}
}
}
int main()
{
int t;cin>>t;
while(t--){
ll l,r;cin>>l>>r;
printf("%lld\n",cou(r)-cou(l-1));
//printf("%lld %lld\n",cou(r),cou(l-1));
}
}
G
给你两个长度为n的数组a,b;你可以交换k次数组a中的两个数,求交换后 的最大值。
对于一组 因为是绝对值,所以是交换a数组,其实也就是交换b数组,所以我们就可以通过交换保证,
那我们就要讨论和
的大小;
情况一
:
不交换的结果:
交换之后的结果:
交换前后的差值:
情况二::
以此类推可以发现,这种情况交换前后的结果没有增加答案的大小。所以不考虑。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
#define debug(x) cout << #x << ": " << x << endl;
int a[N],b[N];
int main(){;
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
ll ans=0;
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
if(a[i]>b[i]) swap(a[i],b[i]);//保证B是更大的那个
ans+=b[i]-a[i];//求没交换之前的答案
}
sort(a+1,a+1+n);//排序,a的最大减b的最小,答案一定最大
sort(b+1,b+1+n);
for(int i=1;i<=k&&i<=n;i++){
int res=2*(a[n+1-i]-b[i]);
if(res>0) ans+=res;
else break;
}
cout<<ans<<endl;
}
查看8道真题和解析

