HZNU Personal Training

B - Infinite Prefixes

 CodeForces - 1295B 

做出前缀a [ i ]  ,那么对于每一个成立的情况  :   a [ i ]  +   k * d  = x

一遍枚举,特判 - 1 和   0的情况。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
ll a[N];
int main(){
     int t;cin>>t;
     while(t--){

        ll n,x;cin>>n>>x;
        
        string s;cin>>s;
        
        ll cur=0,cnt=0;
        bool flag=0;
        
        for(int i=0;i<n;i++){
            if(s[i]=='0')cur++;
            else cur--;

            a[i]=cur;
            if(a[i]==x)flag=1;

        }

        ll d=a[n-1];

        if(x==0)cnt++;
        
        if(d==0&&(flag||x==0)){
            puts("-1");
            continue;
        }

        else if(d==0&&!flag){
            cout<<cnt<<endl;
            continue;
        }
        for(int i=0;i<n;i++){
            if((x-a[i])%d==0&&(x-a[i])/d>=0)cnt++;
        }
        cout<<cnt<<endl;
     }



    // system("pause");
    return 0;
}
View Code

C - Obtain The String

 CodeForces - 1295C

两个字符串,每次从 s 拿出一个子串,问几步构成 t ,

只有26个字母,标记出每个字母出现的下标,每一步记录当前下标,枚举下一个字母出现下标是否在当前下标的后面,二分处理。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
int main(){
     int t;cin>>t;
     while(t--){
        string a,b;
        cin>>a>>b;
        int lena=a.size(),lenb=b.size();
        vector<int>v[30];        
        for(int i=0;i<lena;i++){
            v[ a[i]-'a'].push_back(i);
        }
        bool check=1;
        for(int i=0;i<lenb;i++){
            if(v[b[i]-'a'].empty()){
            check=0;
            break;
            }
        }

        if(!check){
            puts("-1");
            continue;
        }
        for(int i=0;i<26;i++)sort(v[i].begin(),v[i].end());
        int pos=v[ b[0]-'a' ][0],tot=0;
        int ans=1;        
        while(tot<lenb){
                bool flag=0;
                if(tot==lenb-1)break;
                // for(int i=0;i<v[b[tot+1]-'a'].size();i++){
                //     if(v[b[tot+1]-'a'][i]>pos){
                //         pos=v[b[tot+1]-'a'][i];
                //         tot++;
                //         flag=1;
                //         break;
                //     }
                // }
                vector<int>::iterator it;
                it=upper_bound(v[b[tot+1]-'a'].begin(),v[b[tot+1]-'a'].end(),pos);
                if(it!=v[b[tot+1]-'a'].end()){
                    flag=1;
                    pos=*it;
                    tot++;
                }
                if(!flag){
                    ans++;
                    pos=v[b[tot+1]-'a'][0];tot++;
                }
        }
        cout<<ans<<endl;
     }

    // system("pause");
    return 0;
}
View Code

D - Count Triangles

 CodeForces - 1355C 

AxByCzDA≤x≤B≤y≤C≤z≤D 

问  能构成多少个三角形。

考虑只要满足 x + y >  z  即可。

x + y 的范围  [  a+b, b+c ]    

枚举 x +  y  ,判断符合情况的  z  的个数。对答案的贡献即为 cntz  *  x + y 的组合数。

x 在 [ a , b ] , y  在  [ i - b, i - a]  ,y在  [  b , c ] 的范围,取小即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    ll A,B,C,D;
    ll ans=0;
    scanf("%lld %lld %lld %lld",&A,&B,&C,&D);
    for(ll i=A+B;i<=B+C;i++){
        if(i<=C)continue;
        ll cntz=min(i-C,D-C+1);
        ll l=max(i-B,B);
        ll r=min(C,i-A);
        ans+=(r-l+1)*cntz;
    }
    printf("%lld\n",ans);
    // cout<<ans<<endl;
// csC    // system("pause");

    return 0;
}
View Code

D - Phoenix and Science

 CodeForces - 1348D 

设 每天晚上的 细胞数为 ai,那么sum  a i = n

当天分裂多少,对答案的贡献增加多少。

考虑最快的即为倍增,贪心构造即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int t;cin>>t;
    while(t--){
        ll n;
        // scanf("%lld",&n);n
        cin>>n;n--;
                vector<int>a;a.push_back(1);
        for(ll i=2;i<=n;i<<=1){
            a.push_back(i);
            n-=i;
        }
         if(n)a.push_back(n);
         sort(a.begin(),a.end());
         cout<<a.size()-1<<endl;
         for(int i=1;i<a.size();i++){
            // printf("%d ",a[i]-a[i-1]);
        cout<<a[i]-a[i-1]<<" ";
         }
         cout<<endl;

    }


    // system("pause");
    return 0;
}
View Code

C - Hilbert's Hotel

 CodeForces - 1345C 

对于所有的  k   -   >  k + a [  k % n ]

n必然是一个周期。枚举 [ 0, n-1] 投射后的情况,判断有无重合即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
int a[N];
int main(){
    int t;cin>>t;
    while(t--){
    int n;cin>>n;
    map<int,int>mp;
    for(int i=0;i<n;i++){
        cin>>a[i];
        int x=(i+a[i])%n;
        x=(x+n)%n;
        mp[x]++;
    }
    bool flag=1;
    map<int,int>::iterator it;
    for(it=mp.begin();it!=mp.end();it++){
        if(it->second>1){
            flag=0;
            break;
        }
    }
    if(flag)puts("YES");
    else puts("NO");
    }

    // system("pause");
    return 0;
}
View Code

C - Yet Another Counting Problem

 CodeForces - 1342C 

x%a %b  !=  x %b %a 的  情况,从 0 开始,b为一个周期,每次撞到一个lcm(a ,b)即为一个周期的开始,注意区间的头和尾相交的部分 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
int main(){
     int t;cin>>t;
     while(t--){
      ll l,r,a,b,Q;cin>>a>>b>>Q;
      if(a>b)swap(a,b);

        while(Q--){
        cin>>l>>r;
        if(a==1||b==1){
          cout<<0<<" ";
          continue;
        }

        ll tot=r-l+1,d=lcm(a,b);
        
        ll cnt=r/d-(l-1)/d;
        
        ll ld=(l-1)/d*d,rd=r/d*d;
        
        
        if(cnt>=2)tot-=(cnt-1)*b;
        
        if(cnt>=1)tot-=min(r-rd+1,b);

        if(ld+b-1>=l){
        tot-=min(ld+ b-1-l+1,r-l+1);
        // cout<<"test"<<endl;
        }
        tot=max(0ll,tot);
        cout<<tot<<" ";      
      }
      cout<<endl;
      }

    // system("pause");
    return 0;
}
View Code

C - Mixing Water

 CodeForces - 1359C 

考虑交替 h 和 c 偶数必然为( h + c ) / 2   枚举奇数情况,当偶数次数越多,温度越小,二分出一个答案,保证 > = t ,判断  x-1 和  x  那个更接近。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
// #define long double double
double h,c,t;
double f(int x){
  return ( ( x*(c+h) + h ))/ ( (2*x+1) );
}
int main(){
  int T;cin>>T;
    while(T--){
    cin>>h>>c>>t;
    double d=(c+h)/2;
    if(h+c>=2*t){puts("2");continue;}
    if(t>=h){puts("1");continue;}
    int l=0,r=1e9,ans;
    while(l<=r){
      int mid=(l+r)/2;
      if(f(mid)>=t)l=mid+1,ans=mid;
      else r=mid-1;
    }
    if( fabs(f(ans)-t )<=fabs( f(ans+1)-t) ){printf("%d\n",2*ans+1);}
    else printf("%d\n",2*ans+3);


    }
    // system("pause");
  return 0;
}
View Code

C - Nastya and Strange Generator

 CodeForces - 1341C 

每次选取一个x,那么下一个必然是x+1,扫一遍即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+500;
int pos[N],p[N];
int main(){
  int T;cin>>T;
    while(T--){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++){
      scanf("%d",&p[i]);
      pos[ p[i] ]=i;
    }
    bool flag=1;
    for(int i=2;i<=n;i++){
      if(pos[i]>pos[i-1]&&pos[i]!=pos[i-1]+1){flag=0;break;}
    }
    if(flag)puts("Yes");
    else puts("No");
    }

    // system("pause");

  return 0;
}
View Code

D - Nastya and Scoreboard

 CodeForces - 1341D 

记录一个cnt [ i ] [ j ] 表示i个灯变成 j 的代价,那么贪心选择即可,但当前选择的数字可能会造成后面的无解,那么设 f  [ i  ] [ j ] 表示 第 i 位 花费 j  是否可行,

那么从右到左dp出可行解,再从左往右贪心取数字,保证后续过程有解。

#include <bits/stdc++.h>
using namespace std;
const int N=4e3+150;
string s[N];
int f[N][N]={0},w[N][20]={0};
string M[10]={"1110111","0010010","1011101","1011011","0111010","1101011","1101111","1010010","1111111","1111011"};
int main(){
    memset(f,0,sizeof f);
    memset(w,0,sizeof w);
    int n,k;cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>s[i];
    for(int i=1;i<=n;i++){
      for(int j=0;j<=9;j++){
        
        for(int l=0;l<7;l++){
          if(s[i][l]=='0'&&M[j][l]=='1')w[i][j]++;
          else if(s[i][l]=='1'&&M[j][l]=='0'){w[i][j]=-1;break;}
        }

      }
    }

    f[n+1][0]=1;
    for(int i=n;i>=1;i--){
      for(int j=0;j<=9;j++){
        if(w[i][j]==-1)continue;
        for(int l=0;l<=k;l++){
          if(f[i+1][l])f[i][ l + w[i][j] ]=1;
        }
      }
    }

    string ans="";
    
    for(int i=1;i<=n;i++){
      bool flag=0;
      for(int j=9;j>=0;j--){
        if(w[i][j]>k||w[i][j]==-1)continue;
        if(f[ i+1 ][ k - w[i][j] ]==0)continue;
        else {
          flag=1;
          ans+=j+'0';k-=w[i][j];
          break;
        }

      }
    
      if(!flag){ans="-1";break;}
    
    }
    cout<<ans<<endl;
    // system("pause");
    return 0;
}
View Code

C - Linova and Kingdom

 CodeForces - 1337C 

考虑贪心做法,每次选取最外的点,这样贪心,每个点对答案的贡献为  dep [ i ]  -  size [  i  ] ,贪心选择

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
#define pb push_back
vector<int>e[N];
int n,k;
ll size[N],dep[N];
void dfs(int u,int fa){
    size[u]=1;
    for(int i=0;i<e[u].size();i++){
      int v=e[u][i];
      if(v==fa)continue;
      dep[v]=dep[u]+1;
      dfs(v,u);
      size[u]+=size[v];
    }
}
int main(){
    scanf("%d %d",&n,&k);
    for(int i=1,u,v;i<n;i++){
      scanf("%d %d",&u,&v);
      e[u].pb(v);e[v].pb(u);
    }
    dep[1]=0;
    dfs(1,-1);
    // for(int i=1;i<=n;i++)cout<<size[i]-1<<" ";
    // cout<<endl;
    vector<ll>g;
    for(int i=1;i<=n;i++)g.push_back(dep[i]-size[i]+1);
    sort(g.begin(),g.end(),greater<ll>() );
    // for(int i=0;i<n;i++)cout<<g[i]<<" ";
    // cout<<endl;
    ll ans=0;
    for(int i=0;i<k;i++)ans+=g[i];
    cout<<ans<<endl;
    // system("pause");
  return 0;
}
View Code

 

 

posted @ 2020-07-12 00:01  无声-黑白  阅读(128)  评论(0编辑  收藏  举报