ZOJ summer 2018

 

目录

contest-1

1001

1002

1007

contest-2

1010

1011

1012


contest-1

1001

【题意】

查询x到y的路径上边的权值能否组成一个三角形

【题解】

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include<list>
#include <iostream>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 100010;
const int maxm = 200010;

int n,m,tol,head[maxn];
struct edge
{
    int to,cost,next;
}es[maxm];

void addedge( int u , int v , int w )
{
    es[tol].to = v;
    es[tol].cost = w;
    es[tol].next = head[u];
    head[u] = tol++;
}

int fa[maxn],w[maxn],dep[maxn];

void dfs( int u , int f )
{
    for ( int i=head[u] ; i!=-1 ; i=es[i].next )
        if ( es[i].to!=f )
        {
            fa[es[i].to] = u,w[es[i].to] = es[i].cost,dep[es[i].to] = dep[u]+1;
            dfs ( es[i].to , u );
        }
}

int main()
{
    for ( int T ; scanf ( "%d" , &T )==1 ; )
    {
        for ( int Cas=1 ; Cas<=T ; Cas++ )
        {
            scanf ( "%d" , &n );
            tol = 0;
            memset ( head , -1 , sizeof(head) );
            for ( int i=2 ; i<=n ; i++ )
            {
                int u,v,w;
                scanf ( "%d%d%d" , &u , &v , &w );
                addedge( u , v , w );
                addedge( v , u , w );
            }
            dep[1] = 1;
            dfs ( 1 , 0 );
            int que[55];
            printf( "Case #%d:\n" , Cas );
            scanf ( "%d" , &m );
            for ( int i=1 ; i<=m ; i++ )
            {
                int u,v,len = 0;
                scanf ( "%d%d" , &u , &v );
                while ( len<50&&u!=v )
                {
                    if ( dep[u]>dep[v] )
                        que[len++] = w[u],u=fa[u];
                    else
                        que[len++] = w[v],v=fa[v];
                }
                if ( len==50 )
                    printf( "Yes\n" );
                else
                {
                    bool ok = false;
                    sort ( que , que+len );
                    for ( int i=0 ; i<len-2 ; i++ )
                        if ( que[i]+que[i+1]>que[i+2] )
                        {
                            ok = true;
                            break;
                        }
                    if ( ok )
                        printf( "Yes\n" );
                    else
                        printf( "No\n" );
                }
            }
        }
    }
    return 0;
}

1002

【题意】

N个元素中选出连续的一部分,分成>=S个连续的数目相等的元素集合,要求:

1.每个集合中,相邻两个元素颜色不同,

2.每个集合总长度在[L,R]内

【题解】

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 500010;

char s[maxn];
int n,l,r,sl,ans,sum[maxn],last[255],f[maxn<<1];

struct Queue
{
    int q[maxn];
    int qh,qt;
    void Init()
    {
        memset ( q , 0 , sizeof(q) );
        qh = 1;
        qt = 0;
    }
    void Push( int x )
    {
        q[++qt] = x;
        while ( qt>qh&&f[q[qt]]<=f[q[qt-1]] )
            q[qt-1]=q[qt],q[qt--]=0;
    }
    void Move( int x , int len )
    {
        if ( q[qh]+len-1<x )
            q[qh++] = 0;
    }
    int Top()
    {
        return q[qh];
    }
}Q;

int Query( int len )
{
    memset ( f , 0 , sizeof(f) );
    for ( int i=n-len+1 ; i<=n ; i++ )
    {
        memset ( last , 0 , sizeof(last) );
        for ( int j=i,t=1; j>0 ; j-=len,t++ )
        {
            f[j] = min( t-last[s[j]] , f[j+len]+1 );
            last[s[j]] = t;
        }
    }
    int ans=0;
    Q.Init();
    for ( int i=1 ; i<len ; i++ )
        Q.Push(i);
    for ( int i=len ; i+(sl-1)*len<=n ; i++ )
    {
        Q.Push(i); Q.Move( i , len );
        if ( f[Q.Top()]>=sl )
            ans = max ( ans , sum[(i-len+1)+len*f[Q.Top()]-1]-sum[i-len] );
    }
    return ans;
}

int main()
{
    for ( int T ; scanf ( "%d" , &T )==1 ; )
    {
        for ( int Cas=1 ; Cas<=T ; Cas++ )
        {
            sum[0] = 0;
            scanf( "%d%d%d%d" , &n , &l , &r , &sl );
            scanf( "\n" );
            for ( int i=1 ; i<=n ; i++ )
                s[i] = getchar();
            scanf( "\n" );
            for ( int i=1 ; i<=n ; i++ )
                sum[i] = sum[i-1]+getchar()-'0';
            ans = 0;
            for ( int i=l ; i<=r ; i++ )
                ans = max ( ans , Query(i) );
            printf( "%d\n" , ans );
        }
    }
    return 0;
}

1007

【题意】

从1~N中不重复的选至少K个数,要求这K个数的乘积不能被除1以外的平方数除尽,求这K个数的和

【题解】

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 510;

vector<int>G[maxn];
int dp[maxn][1<<8],n,k;
int p[8] = { 2,3,5,7,11,13,17,19 };

void Mod( int &x ){ x%=mod; }

void check( int x )
{
    int s = 0;
    for ( int i=0 ; i<8 ; i++ )
        if ( x%p[i]==0 )
        {
            x /= p[i];
            s |= 1<<i;
            if ( x%p[i]==0 )
                return;
        }
    G[x].push_back(s);
}

int main()
{
    for ( int T ; scanf ( "%d" , &T )==1 ; )
    {
        for ( int Cas=1 ; Cas<=T ; Cas++ )
        {
            scanf( "%d%d" , &n , &k );
            for ( int i=1 ; i<=n ; i++ )
                G[i].clear();
            for ( int i=1 ; i<=n ; i++ )
                check( i );
            memset ( dp , 0 , sizeof(dp) );
            dp[0][0] = 1;
            for ( int i=0 ; i<G[1].size() ; i++ )
                for ( int j=k-1 ; j>=0 ; j-- )
                    for ( int s=0 ; s<(1<<8) ; s++ )
                        if ( dp[j][s]&&!(s&G[1][i]) )
                            Mod( dp[j+1][s|G[1][i]]+=dp[j][s] );
            for ( int i=2 ; i<=n ; i++ )
                if ( G[i].size() )
                    for ( int j=k-1 ; j>=0 ; j-- )
                        for ( int s=0 ; s<(1<<8) ; s++ )
                            if ( dp[j][s] )
                                for ( int t=0 ; t<G[i].size() ; t++ )
                                    if ( !(s&G[i][t]) )
                                        Mod( dp[j+1][s|G[i][t]]+=dp[j][s] );
            int ans = 0;
            for ( int i=1 ; i<=k ; i++ )
                for ( int j=0 ; j<(1<<8) ; j++ )
                    ans = ( ans+dp[i][j] )%mod;
            printf( "%d\n" , ans );
        }
    }
    return 0;
}

contest-2

1010

【题意】

杨辉三角形第k行有几个奇数

【题解】

奇数个数 = 2^e,(e : k-1 的二进制表示中1的个数)

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include<list>
#include <iostream>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int maxn = 100010;
const int mod  = 1e9+7;

int main()
{
    ll k;
    while(scanf("%lld",&k) != EOF)
    {
        ll res = 1;
        k--;
        while(k)
        {
            if(k & 1)
                res = res*2;
            k >>= 1;
        }
        printf("%lld\n",res);
    }
    return 0;
}

1011

【题意】

有1元硬币:M个,100元:无数

共N天,i-th天,花费 = C[i] 元 ,不开心系数 = W[i],

不开心值 = (找钱数) * (不开心系数),求N天不开心值总和的最小值

【题解】

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;

int c[maxn];
int w[maxn];

int main()
{
    for ( int T ; scanf ( "%d" , &T )==1 ; )
    {
        for ( int Cas=1 ; Cas<=T ; Cas++ )
        {
            int n,m; 
            scanf ( "%d%d" , &n , &m );
            for ( int i=1 ; i<=n ; i++ )
                scanf ( "%d" , &c[i] ),c[i] %= 100;
            for ( int i=1 ; i<=n ; i++ )
                scanf ( "%d" , &w[i] );
            LL ans = 0;
            priority_queue< LL,vector<LL>,greater<LL> >Q;
            for ( int i=1 ; i<=n ; i++ )
            {
                if ( c[i] )
                    Q.push( LL(w[i]*(100-c[i])) );
                if ( m>=c[i] )
                    m -= c[i];
                else
                {
                    m += 100-c[i];
                    ans += Q.top();
                    Q.pop();
                }
            }
            printf ( "%lld\n" , ans );
        }
    }
    return 0;
}

1012

【题意】

 

【题解】

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include<list>
#include <iostream>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 3e6+5;
const int inf  = 0x3f3f3f3f;

bool isprime[110];
int primes[110],len;

void Get_prime()
{
    len = 0;
    memset ( isprime , true , sizeof(isprime) );
    isprime[0] = false;
    isprime[1] = false;
    for ( int i=2 ; i<=100 ; i++ )
    {
        if ( isprime[i] )
            primes[++len] = i;
        for ( int j=1 ; j<=len ; j++ )
        {
            if ( i*primes[j]>100 )
                break;
            isprime[i*primes[j]] = false;
            if ( i%primes[j]==0 )
                break;
        }
    }
}

int l,r,p,tp;
int a[maxn],b[maxn],s[maxn];

void dfs( int x , int y )
{
    if ( x>len||primes[x]>p||primes[x]>r/y )
        return;
    dfs( x+1 , y );
    while ( primes[x]<=r/y )
    {
        a[++tp] = y*primes[x];
        y *= primes[x];
        dfs( x+1 , y );
    }
}

int main()
{
    Get_prime();
    for ( int T ; scanf ( "%d" , &T )==1 ; )
    {
        for ( int Cas=1 ; Cas<=T ; Cas++ )
        {
            scanf ( "%d%d%d" , &l , &r , &p );
            a[tp=1] = 1;
            dfs ( 1 , 1 );
            sort ( a+1 , a+tp+1 );
            for ( int i=1 ; i<=tp ; i++ )
                b[i] = inf,s[i] = 0;
            b[1] = 0;
            for ( int i=2 ; i<=p ; i++ )
            {
                int tpos = 1;
                for ( int j=1 ; j<=tp ; j++ )
                {
                    if ( a[tpos]>a[tp]/i )
                        break;
                    while ( tpos<j&&a[tpos]*i<a[j] )
                        tpos++;
                    if ( a[tpos]*i==a[j] )
                        b[j] = min( b[j] , b[tpos]+1 );
                    if ( b[j]+i<=p )
                        s[j] = 1;
                }
            }
            int ans = 0;
            for ( int i=1 ; i<=tp ; i++ )
                if ( s[i]&&a[i]>=l )
                    ans++;
            printf( "%d\n" , ans );
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值