牛客寒假训练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\n",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 待补

猜你喜欢

转载自www.cnblogs.com/Accepting/p/12263360.html
今日推荐