zoukankan      html  css  js  c++  java
  • 牛客寒假训练1

    ------------恢复内容开始------------

    A honoka和格点三角形

    题解:计算几何加容斥。

    先固定一个底边长度为1,那么高度一定为2,固定长度为2,高度一定为1,这样计算出来的好三角形的个数为 (m-1)*m*(n-2)*2+(m-2)*m*(n-1)*2+(n-1)*n*(m-2)*2+(n-2)*n*(m-1)*2。

    然后画图可以知道每一个直角三角形都计算了两次,然后在减去直角三角形的个数((m-1)*(n-2)*2+(n-1)*(m-2)*2)*2;

    注意计算的时候一定要分开来算,小心爆long long .

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    int main()
    {
        ll n,m;
        cin>>n>>m;
        ll ans1,ans;
    //    ll ans=(m-1)*m*(n-2)*2+(m-2)*m*(n-1)*2;
        ll ansa,ansb;
        ansa=(m-1)*m%mod;
        ansa=ansa*(n-2)%mod;
        ansa=ansa*2%mod;
        ansb=(m-2)*m%mod;
        ansb=ansb*(n-1)%mod;
        ansb=ansb*2%mod;
        ll ans3;
        ll ans4;
    //    ll ans2=(n-1)*n*(m-2)*2+(n-2)*n*(m-1)*2;
    
        ans3=(n-1)*n%mod;
        ans3=ans3*(m-2)%mod;
        ans3=ans3*2%mod;
    
        ans4=(n-2)*n%mod;
        ans4=ans4*(m-1)%mod;
        ans4=ans4*2%mod;
        ans=(ansa+ansb)%mod;
        ans=(ans+(ans3+ans4)%mod)%mod;
        ll sum=((m-1)*(n-2)*2%mod+(n-1)*(m-2)*2%mod)*2%mod;
        cout<<(ans-sum+mod)%mod<<endl;
        return 0;
    }

    B kotori和bangdream

    这个题目要用double 。不然会爆精度

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
        double n,x,a,b;
        cin>>n>>x>>a>>b;
        double x1=x/100.0;
        double x2=a*x1+b*(1-x1);
        printf("%.2lf
    ",x2*n);
        return 0;
    }

    C 待补 

    D hanayo和米饭 签到

    E rin和快速迭代

    考查质因子分解求因子的个数。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=200;
    int arr[N];
    ll f(ll n){
        ll s=1;
        for(ll i=2;i*i<=n;i++){
            if(n%i==0){
                ll a=0;
                while(n%i==0){
                    n/=i;
                    a++;
                }
                s=s*(a+1);
            }
        }
        if(n>1) s=s*2;
        return s;
    }
    int main(){
        ll n;
        cin>>n;
        ll time=0;
        ll x=n;
        while(x!=2){
            x=f(x);
            time++;
        }
        cout<<time<<endl;
        return 0;
    }

    F maki和tree

    对树的理解有问题。。。对每一个黑点,我们求出与它直接相连接的白点的连通白点的个数(也可以直接求出每个白点的联通个数)。然后想想看,同一个黑点两个白点如果这两个白点想要相互访问,那么一定会经过该黑点。对同一个黑点连接的两个白点a和b,答案就是a的联通个数乘以b的联通个数,然后在加上a和b的各自的联通个数。

    即答案为:

    for(int i=0;i<pos;i++){

      for(int j=i+1;j<pos;j++)

        ans+=dis[i]*dis[j];

      ans+=dis[i]

    }

    由于是相乘,我们可以预处理前缀和,然后可以把复杂度降为o(n)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=1E5+7;
    char s[N];
    vector<ll >ve[N];
    ll dis[N];
    ll mark[N];
    ll arr[N];
    ll d[N];
    ll bfs(ll x){
        queue<ll >que;
        que.push(x);
        ll ans=0;
        while(que.size()){
            ll a=que.front();
            que.pop();
            ans++;
            mark[a]=x;
            for(ll i=0;i<ve[a].size();i++){
               ll c=ve[a][i];
               if(!mark[c]&&s[c]=='W') que.push(c);
            }
        }
        return ans;
    }
    int main(){
        ll n;
        cin>>n;
        scanf("%s",s+1);
        ll x,y;
        for(ll i=1;i<=n-1;i++){
            cin>>x>>y;
            ve[x].push_back(y);
            ve[y].push_back(x);
        }
        for(int i=1;i<=n;i++){
            if(s[i]=='W'){
                if(mark[i]!=0) dis[i]=dis[mark[i]];
                else dis[i]=bfs(i);
            }
        }
        ll ans=0;
        for(ll i=1;i<=n;i++){
            if(s[i]=='B'){
                ll pos=0;
                ll sum=0;
                for(ll j=0;j<ve[i].size();j++){
                    if(s[ve[i][j]]=='W'){
                        arr[pos++]=ve[i][j];
    
                    }
                }
                d[arr[0]]=dis[arr[0]];
                for(int i=1;i<pos;i++){
                    d[arr[i]]=d[arr[i-1]]+dis[arr[i]];
                }
                for(int i=0;i<pos;i++){
                    ans+=dis[arr[i]]*(d[arr[pos-1]]-d[arr[i]])+dis[arr[i]];
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }

    G eli和字符串:

    VECTOR保存每个字符的位置。然后暴力枚举

    #include<bits/stdc++.h>
    using namespace std;
    const int INF=1E9+7;
    vector<int >ve[10000];
    int main(){
        int n,k;
        cin>>n>>k;
        string s;
        cin>>s;
        for(int i=0;i<n;i++){
            ve[s[i]].push_back(i);
        }
        int ans=INF;
        for(char i='a';i<='z';i++){
            int x=ve[i].size();
            if(x<k) continue ;
            for(int j=0;j<=x-k;j++){
                ans=min(ans,ve[i][j+k-1]-ve[i][j]+1);
            }
        }
        if(ans==INF) cout<<-1<<endl;
        else cout<<ans<<endl;
    
        return 0;
    }

    nozomi和字符串

    二分答案+双指针

    check(int x)函数的书写:用双指针,求出长度为x时的0的个数与1的个数,然后向右滑动,同时判断只要0和1的个数有一个小于等于k就满足条件

    #include<bits/stdc++.h>
    using namespace std;
    int n,k;
    string s;
    bool check(int x){
        int a0=0,a1=0;
        int l=0,r=x-1;
        for(int i=0;i<=x-1;i++){
            if(s[i]=='0') a0++;
            else a1++;
        }
        if(a0<=k||a1<=k) return 1;
        l++,r++;
        for(;l<=n-x&&r<=n-1;l++,r++){
            if(s[l-1]=='0') a0--;
            else a1--;
            if(s[r]=='0') a0++;
            else a1++;
            if(a0<=k||a1<=k) return 1;
        }
        return 0;
    }
    
    int main(){
        cin>>n>>k;
        cin>>s;
        int left=0;
        int right=n;
        int ans=0;
        check(4);
        while(left<=right){
            int mid=(left+right)/2;
            if(check(mid)){
                left=mid+1;
                ans=max(ans,mid);
            }
            else {
                right=mid-1;
            }
        }
        cout<<ans<<endl;
        return 0;
    }

    nico和niconiconi

    DP问题

    以最后一个字符为标准,判断前面的字符满足那个条件

    满足条件a的话,答案为dp[i]=max(dp[i],dp[i-4]+a)

    满足条件b的话,答案为dp[i]=max(dp[i],dp[i-6]+a)  ,dp[i]=max(dp[i],dp[i-6]+b)

    满足条件c的话,答案为dp[i]=max(dp[i],dp[i-10]+c),dp[i]=max(dp[i],dp[i-10]+a+b),dp[i]=max(dp[i],dp[i-10]+a+a)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=3e5+7;
    char s[N];
    ll dp[N];
    int main()
    {
        ll n,a,b,c;
        cin>>n>>a>>b>>c;
        scanf("%s",s+1);
        for(ll i=1;i<=n;i++){
            dp[i]=max(dp[i],dp[i-1]);
            if(s[i]=='o'&&i>=4){
                if(s[i-1]=='c'&&s[i-2]=='i'&&s[i-3]=='n') dp[i]=max(dp[i],dp[i-4]+a);
            }
            if(s[i]=='i'&&i>=6){
                if(s[i-1]=='n'&&s[i-2]=='o'&&s[i-3]=='c'&&s[i-4]=='i'&&s[i-5]=='n'){
                    dp[i]=max(dp[i],dp[i-6]+b);
                    dp[i]=max(dp[i],dp[i-6]+a);
                }
            }
            if(s[i]=='i'&&i>=10){
                if(s[i-1]=='n'&&s[i-2]=='o'&&s[i-3]=='c'&&s[i-4]=='i'&&s[i-5]=='n'&&s[i-6]=='o'&&s[i-7]=='c'&&s[i-8]=='i'&&s[i-9]=='n'){
                    dp[i]=max(dp[i],dp[i-10]+c);
                    dp[i]=max(dp[i],dp[i-10]+a+b);
                    dp[i]=max(dp[i],dp[i-10]+a+a);
                }
            }
        }
        cout<<dp[n]<<endl;
    
    
        return 0;
    }

    J 待补

  • 相关阅读:
    SpringMVC与uploadify结合进行上传
    SpringMVC使用MultipartFile文件上传,多文件上传,带参数上传
    file.delete()与file.deleteOnExit(); 的区别
    快速遍历目录下所有文件名
    使用SpringMVC框架解决中文乱码的问题
    SpringCloud微服务基础
    Linux常用命令
    Linux安装软件
    MySQL 树节点递归遍历所以子节点
    微软Office Online服务安装部署(三)
  • 原文地址:https://www.cnblogs.com/Accepting/p/12263360.html
Copyright © 2011-2022 走看看