牛客周赛 Round 55(解题)

小红的字符串

代码

#include<iostream>
#include<map>

using namespace std;

string a;
map<char,int>S;

int main(){
    cin>>a;
    
    for(int i=0;i<a.size();i++){
        S[a[i]]++;
    }
    int maxv=0;
    for(auto [v,w]:S){
        maxv=max(maxv,w);
    }
    
    cout<<a.size()-maxv;
    
    return 0;
    
}

小红的序列乘积

思路

就是直接看个位数就可以了,别的不管。

#include<iostream>

#define int long long

using namespace std;

const int N = 2e5+10;

int w[N];
int n;
int res;

signed main(){
    cin>>n;
    int sum=1;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        
        int k=x%10;
        sum*=k;
        sum%=10;
        // cout<<k<<endl;
        if(sum%10==6){
            res++;
        }
        
    }
    
    cout<<res;
    
    return 0;
    
}

小红的数组重排

思路

我们就直接排个序即可。

#include<iostream>
#include<algorithm>

#define int unsigned long long

using namespace std;

const int N = 5e5+10;

int w[N];
int a[N],b[N];
int n;
int m1,m2;

signed main(){
    cin>>n;
    
    for(int i=1;i<=n;i++)cin>>w[i];
    
    sort(w+1,w+1+n);
    
    bool f=false;
    for(int i=1;i<n-1;i++){
        if(w[i]*w[i+1]>=w[i+1]*w[i+2]){
            f=true;
            break;
        }
    }
    
    if(f)puts("NO");
    else{
        puts("YES");
        for(int i=1;i<=n;i++){
            cout<<w[i]<<' ';
        }
    }
    
    return 0;
}

虫洞操纵者

思路

本质上就是bfs,但只不过我们这道题建图有点麻烦,我们得考虑每行的最近点对和每列的,我们要搞虫洞,我们可以用二维数组来装一下在 ( x , y ) (x,y) (x,y) 坐标下,每行或每列的最近 1 1 1 的位置,然后每行每列找到之后,我们就将它们建图,最后我们只需要跑个最短路(我这边用的是bfs)即可解决。

  • 这边注意一下的就是,我们是扩展了图,就是把给定的图的外部全部设为 1。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

#define x first
#define y second

using namespace std;

typedef pair<int,int>PII;

const int N = 3e6+10,M = 4*N,S=1e3+10;

int e[M],ne[M],h[N],idx;
bool st[N];
int n;
int dist[N];
int w[S][S];
queue<int>q;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int pre[S][S],up[S][S];

int get(int x,int y){
    return (x-1)*n+y;
}

void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

int bfs(){
    
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    
    q.push(1);
    
    
    while(q.size()){
        int ver=q.front();
        q.pop();
        
        for(int i=h[ver];~i;i=ne[i]){
            int j=e[i];
            if(dist[j]>dist[ver]+1){
                dist[j]=dist[ver]+1;
                q.push(j);
                // cout<<(j-1)/n+1<<' '<<(j-1)%n+1<<endl;
            }
        }
    }
    return dist[n*n];
}

int main(){
    cin>>n;
    
    for(int i=0;i<=n+5;i++){
        for(int j=0;j<=n+5;j++){
            w[i][j]=1;
        }
    }
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>w[i][j];
        }
    }
    
    memset(h,-1,sizeof h);
    
    for(int i=1;i<=n+1;i++){
//         pre[i][0]=0;
        for(int j=1;j<=n+1;j++){
            if(w[i][j]==1){
                pre[i][j]=j;
            }else{
                pre[i][j]=pre[i][j-1];
            }
        }
    }
    
    for(int j=1;j<=n+1;j++){
//         up[0][j]=0;
        for(int i=1;i<=n+1;i++){
            if(w[i][j]==1){
                up[i][j]=i;
            }else{
                up[i][j]=up[i-1][j];
            }
        }
    }
    
    
    for(int i=1;i<=n+1;i++){
        for(int j=1;j<=n+1;j++){
            if(i==n+1&&j==n+1)continue;
            if(w[i][j]==1){
                if(j>=2&&w[i][j-1]==0){
                    add(get(i,j-1),get(i,pre[i][j-1]+1));
                    add(get(i,pre[i][j-1]+1),get(i,j-1));
                }
                if(i>=2&&w[i-1][j]==0){
                    add(get(i-1,j),get(up[i-1][j]+1,j));
                    add(get(up[i-1][j]+1,j),get(i-1,j));
                }
            }
        }
    }
    
    
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(w[i][j]==0){
                for(int k=0;k<4;k++){
                    int a=dx[k]+i,b=dy[k]+j;
                    if(a<1||b<1||a>n||b>n||w[a][b]==1)continue;
                    add(get(i,j),get(a,b));
                    add(get(a,b),get(i,j));
                }
            }
            
        }
    }
    
    int t=bfs();
    
    if(t>0x3f3f3f3f/2)puts("-1");
    else cout<<t;

    
    return 0;
}

小红的序列乘积2.0

思路

这道题就是dp问题,类似数位dp,我们可以设:f[i][j]表示已经到了第i个位置,当前位的是j的方案数集合。

那么它的状态转移也很容易:

f[i][j*w[i]%10]=f[i-1][j]+f[i][j*w[i]%10]
然后如果当前位是 6 的话,我们就 f[i-1][j]*2^{n-i} 即可。(为什么是这个式子呢,因为前面的位数已经定下来了,后面的位数的方案是 2 n − i 2^{n-i} 2ni,也就是选和不选两种情况)

//数位dp,f[i][j]表示已经到了第i个位置,当前位的是j的方案数集合

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

using namespace std;

#define int long long

const int N = 1e5+10,mod=1e9+7;

int f[N][12],g[N];
int n;
int w[N];

int qmi(int a,int b){
    int res=1;
    
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

signed main(){
    cin>>n;
    
    for(int i=1;i<=n;i++)cin>>w[i],w[i]%=10;
    
    f[0][1]=1;
    
    int ans=0;
    
    for(int i=1;i<=n;i++){
        for(int j=0;j<10;j++){
            (f[i][j]+=f[i-1][j])%=mod;
            (f[i][j*w[i]%10]+=f[i-1][j])%=mod;
            if(j*w[i]%10==6){
                (ans+=f[i-1][j]*qmi(2,n-i))%=mod;
            }
        }
    }
    
    cout<<ans;
    
    return 0;
    
}

灯下定影

思路

这道题就是计算几何的基础应用,其实就是算直线跟圆的交点,然后所有交点算完之后存储起来最后做区间合并就可以了。

代码(包含计算几何的部分板子)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>

#define x first
#define y second

using namespace std;

typedef pair<double,double>PDD;

const int N = 1e5+10;
const double eps=1e-8;
const double PI=acos(-1);

double r,x;
int n;
vector<PDD> v;

int sign(double x){
    if(x<0)return -1;
    if(fabs(x)<eps)return 0;
    return 1;
}

int cmp(double x,double y){
    if(x<y)return -1;
    if(fabs(x-y)<eps)return 0;
    return 1;
}

PDD operator+(PDD a,PDD b){
    return {a.x+b.x,a.y+b.y};
}

PDD operator-(PDD a,PDD b){
    return {a.x-b.x,a.y-b.y};
}

PDD operator/(PDD a,double t){
    return {a.x/t,a.y/t};
}

double operator*(PDD a,PDD b){
    return a.x*b.y-a.y*b.x;
}

double operator&(PDD a,PDD b){
    return a.x*b.x+a.y*b.y;    
}

double get_len(PDD a){
    return sqrt(a&a);
}

PDD operator*(PDD a,double b){
    return {a.x*b,a.y*b};
}

double area(PDD a,PDD b,PDD c){
    return (b-a)*(c-a);
}

bool on_segment(PDD p,PDD a,PDD b){
    return sign((p-a)&(p-b))<=0;
}

PDD get_line_intersaction(PDD p,PDD v,PDD q,PDD w){
    PDD u=p-q;
    double t=(w*u)/(v*w);
    return p+v*t;
}

double get_dist(PDD a,PDD b){
    double dx=a.x-b.x;
    double dy=a.y-b.y;
    return sqrt(dx*dx+dy*dy);
}

int main(){
    PDD p0;
    cin>>p0.x>>p0.y>>r>>n>>x;
    
    for(int i=1;i<=n;i++){
        PDD p1,p2;
        double s;
        cin>>p1.x>>p1.y>>p2.x>>p2.y>>s;
        PDD v1=p0-p1;
        PDD v2=p2-p1;
        double len1=(v1&v2)/get_len(v2);
        
        if(len1<0)continue;
        
        double len2=get_len(v1);
        double len3=sqrt(len2*len2-len1*len1);//圆心到直线的距离
        
        if(len3>r)continue;
        
        double len4=sqrt(r*r-len3*len3);
        
        double xl=(len1-len4)/s;
        double xr=(len1+len4)/s+x;
        v.push_back({xl,xr});
    }
    
    
    sort(v.begin(),v.end());
    
    double ans=0;
    
    double l=0,r=0;
    
    for(auto& [xl,xr]:v){
        // cout<<xl<<' '<<xr<<endl;
        if(r<xl){
            ans+=r-l;
            l=xl,r=xr;
        }else{
            r=max(xr,r);
        }
    }
    
    ans+=r-l;
    
    printf("%.10lf",ans);
    
    return 0;
    
}
  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

green qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值