Codeforces Round #548 (Div. 2)

http://codeforces.com/contest/1139

A Even Substrings

求偶数。
只要保证个位能够被2整除就是偶数。所以从后向前遍历。

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;

void cfA(){
    int n; cin>>n;
    string str; cin>>str;
    int ans=0;
    for(int i=n-1;i>=0;i--){
        if((str[i]-48)%2==0) ans+=i+1;
    }
    cout<<ans<<endl;
}

int main(){
    cfA();
    return 0;
}

B Chocolates

题目关键是 x j &lt; x i x_j&lt;x_i xj<xi,其中 j &lt; i j&lt;i j<i,从中需要得出一个结论,就是最后一个元素不管是多少都必须要选。 因为它必须要比前面的元素大,而且因为它最后面,需要自身尽可能的大,所以最后一个元素一定选它自身的值。

这样从后先前搜索即可。

此题答案需要开 long long

#include<iostream>
#include<cstdlib>
using namespace std;

int inte[200010];

void cfB(){
    int n; cin>>n;
    for(int i=0;i<n;i++) cin>>inte[i];

    //the last one must choose
    long long ans=inte[n-1];
    int pre=inte[n-1];  //the previous
    for(int i=n-2;i>=0;i--){
        if(inte[i]<pre){   //the next is inte[i]
            ans+=inte[i];
            pre=inte[i];
        }else{
            pre-=1;
            if(pre<0) pre=0;   //it is positive
            
            ans+=pre;   //the previous -1
            
        }
    }

    cout<<ans<<endl;
}

int main(){
    cfB();
    return 0;
}

C Edgy Trees

并查集
并查集模板

//union
void init(int n){
    for(int i=0;i<n;i++){
        par[i]=i;   //each is the root of itself
        rank1[i]=0;
    }
}

int find(int x){
    if(par[x]==x) return x;
    else{
        return par[x]=find(par[x]);  //at the time of searching,short the way to root

    }
}

void merge(int x,int y){
    int xx=find(x);
    int yy=find(y);
    if(xx==yy) return ;
    
    if(rank1[xx]<rank1[yy]){
        par[xx]=yy;
    }else{
        par[yy]=xx;
        if(rank1[xx]==rank1[yy]) rank1[xx]++;
    }
}

快速幂

快速幂就是为了快速求幂,
如: x y x^y xy ,按照朴素算法就是把x连乘y次,
普通做法时间复杂度是 O ( y ) O(y) O(y) O ( n ) O(n) O(n)
快速幂时间复杂度为 O ( l o g n ) O(logn) O(logn)

快速幂

快速幂模板:

long long powx(int x,int y){
    long long ans=1; 
    long long base=x;
    while(y!=0){        //when all the bit lose,y==0
        if(y&1!=0){     //the lowest of y is 1
            ans*=base;
        }
        base*=base;
        y>>=1;      //move one bit to right
    }
}

题解博客
在长度为 k k k的序列里,由于每个位置有 n n n种可能,所以总的可能数为 n k n^k nk用总的可能数减去仅经过红边的序列数即可。
由于仅经过红边说明在这些节点在同一个连通区域,并且相互之间只有红边相连。

( n k − ∑ i = 1 n u m s u m [ i ] k + m o d ) % m o d (n^k− \sum_{i=1}^{num}sum[i]^k+mod)\%mod (nki=1numsum[i]k+mod)%mod

#include<iostream>
#include<vector>
#include<cstdlib>
using namespace std;

int par[100010];
int rank1[100010];
int sum[100010];
long long mod_number=1e9+7;


long long powx(int x,int y){
    long long ans=1; 
    long long base=x;

    while(y!=0){        //when all the bit lose,y==0
        if(y&1!=0){     //the lowest of y is 1
            ans*=base;  ans%=mod_number;
        }
        base*=base; base%=mod_number;
        y>>=1;      //move one bit to right
    }

    return ans;
}


//union
void init(int n){
    for(int i=0;i<=n;i++){
        par[i]=i;   //each is the root of itself
        rank1[i]=0;
        sum[i]=1;
    }
}

int find(int x){
    if(par[x]==x) return x;
    else{
        return par[x]=find(par[x]);  //at the time of searching,short the way to root
    }
}


void merge(int x,int y){
    int xx=find(x);
    int yy=find(y);
    if(xx==yy) return;
    
    if(rank1[xx]<rank1[yy]){
        par[xx]=yy;
        sum[yy]+=sum[xx];   //the sum number of the union
    }else{
        par[yy]=xx;
        if(rank1[xx]==rank1[yy]) rank1[xx]++;
        sum[xx]+=sum[yy];  //the sum number of the union
    }
    
}

void cfC(){
    int n,k; cin>>n>>k;
    init(n);
    for(int i=1;i<=n-1;i++){
        int x1,y1,w; cin>>x1>>y1>>w;
        if(w==0){
            merge(x1,y1);  //add to graph
        }
    }


    //check all the gather
   long long summ=0;
    for(int i=1;i<=n;i++){
        if(par[i]==i){
           summ+=powx(sum[i],k);
           summ%=mod_number;
        }
    }

    cout<<(powx(n,k)-summ+mod_number)%mod_number<<endl;
}

int main(){
    cfC();
    // system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值