HIAST Collegiate Programming Contest 2024(非完全题解)

C题(简单数据结构+二分)

转化成对每个i,求最长区间使得区间与为ai。左右边界可以二分出来(类似24新生赛B),区间与用st表

// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
// //如果在不支持 avx2 的平台上将 avx2 换成 avx 或 SSE 之一
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
// inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline ll Lsqrt(ll x) { ll L = 1,R = 2e9;while(L + 1 < R){ll M = (L+R)/2;if(M*M <= x) L = M;else R = M;}return L;}
#define N 100005
int f[25][N];
int Log2[N];
int n,a[N];
int query(int l,int r)
{
    int k = Log2[r-l+1];
    return f[k][l] & f[k][r-(1<<k)+1];
}

void solve()
{
    cin>>n;
    for(int i=1;i<=n;++i) cin>>a[i], f[0][i]=a[i];
    for(int j=1;j<=Log2[n];++j)
    {
        for(int i=1;i+(1<<j-1)<=n;++i)
        {
            f[j][i] = (f[j-1][i] & f[j-1][i+(1<<j-1)]);
        }
    }

    for(int i=1;i<=n;++i)
    {
        int l,r,mid;
        int L,R;
        l=1; r=i;
        while(l<r)
        {
            mid = (l+r)>>1;
            if(query(mid, i) == a[i]) r=mid;
            else l=mid+1;
        }
        L=l;
        l=i, r=n;
        while(l<r)
        {
            mid = (l+r+1)>>1;
            if(query(i, mid) == a[i]) l=mid;
            else r=mid-1;
        }
        R=l;
        cout<<(ll)(R-i+1)*(i-L+1)<<' ';
    }
    cout<<'\n';
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
    Log2[0]=-1;
    for(int i=1;i<N;++i) Log2[i] = Log2[i/2]+1;
	int T;
	cin>>T;
	while(T--)
	{
		solve();
	}
}

H(博弈)

\(关注到不管是移动一个还是三个都会改变sum的奇偶性\)

    // #pragma GCC optimize("O3,unroll-loops")
    // #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
    // //如果在不支持 avx2 的平台上将 avx2 换成 avx 或 SSE 之一
    #include<bits/stdc++.h>
    using namespace std;
    #define x first
    #define y second
    typedef pair<int,int> PII;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef unsigned int uint;
    typedef vector<string> VS;
    typedef vector<int> VI;
    typedef vector<vector<int>> VVI;
    vector<int> vx;
    inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
    inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
    inline int log_2(int x) {return 31-__builtin_clz(x);}
    inline int popcount(int x) {return __builtin_popcount(x);}
    inline int lowbit(int x) {return x&-x;}
    inline ll Lsqrt(ll x) { ll L = 1,R = 2e9;while(L + 1 < R){ll M = (L+R)/2;if(M*M <= x) L = M;else R = M;}return L;}
    void solve()
    {
        int n;
        cin>>n;
        int a;
        ll sum = 0;
        for(int i=0;i<n;++i)
        {
            cin>>a;
            sum += a;
        }
        cout<<((sum&1)?("YES\n"):("NO\n"));
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int T;
        cin>>T;
        while(T--)
        {
            solve();
        }
    }

I(纯签到)

\(注意find函数若没找到是!=npos没有括号\)

// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
//如果在不支持 avx2 的平台上将 avx2 换成 avx 或 SSE 之一
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
// inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline ll Lsqrt(ll x) { ll L = 1,R = 2e9;while(L + 1 < R){ll M = (L+R)/2;if(M*M <= x) L = M;else R = M;}return L;}
void solve()
{
    string s;
    cin>>s;
    string std = "bitset";
    if(s.find(std) != s.npos)
    {
        cout<<"7as\n";
    }
    else
    {
        cout<<"no 7as for you today\n";
    }
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		solve();
	}
}

K题(LCA,dfs序,思维)

倒水问题,可以发现对一个子树,从根开始倒水,结点进水顺序为dfs序。
对每个询问,从v开始倒水要想去u,必定经过lca(u,v),过程可以分为两部分,从v到r和从r到u,分类讨论求代价即可。

// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
//如果在不支持 avx2 的平台上将 avx2 换成 avx 或 SSE 之一
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline ll Lsqrt(ll x) { ll L = 1,R = 2e9;while(L + 1 < R){ll M = (L+R)/2;if(M*M <= x) L = M;else R = M;}return L;}

#define N 100005
int n,q;
vector<int> e[N];
vector<int> edfn[N];
int fa[N], siz[N], dep[N], son[N], top[N];
int dfn[N];
int tot;
void dfs_init(int u)
{
    siz[u] = 1;
    son[u] = 0;
    dfn[u] = ++tot;
    for(auto &&v:e[u])
    {
        dep[v] = dep[u] + 1;
        dfs_init(v); 
        siz[u] += siz[v];
        if(siz[v] > siz[son[u]]) son[u] = v;
    }

    edfn[u].resize(e[u].size());
    for(int i=0;i<e[u].size();++i)
    {
        edfn[u][i] = dfn[e[u][i]];
    }
}
void dfs_shupou(int u,int topx)
{
    top[u] = topx;
    if(son[u]) dfs_shupou(son[u], topx);
    for(auto &&v:e[u])
    {
        if(v==son[u]) continue;
        dfs_shupou(v, v);
    }
}
int lca(int x,int y)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]]) swap(x,y);
        x = fa[top[x]];
    }
    if(dep[x] < dep[y]) return x;
    else return y;
}

void solve()
{
    cin>>n>>q;
    tot = 0;
    for(int i=1;i<=n;++i) e[i].clear(), edfn[i].clear();
    for(int i=2;i<=n;++i)
    {
        cin>>fa[i];
        e[fa[i]].push_back(i);
    }
    for(int i=1;i<=n;++i) sort(e[i].begin(),e[i].end());
    dep[1]=0;
    dfs_init(1);
    dfs_shupou(1,1);

    while(q--)
    {
        int v,x,u; cin>>v>>x>>u;
        auto f = [&](int y){cout<<(x>=y?"YES\n":"NO\n");};
        if(u==v) {f(1); continue;}
        
        int r = lca(v,u);
        // int fu = e[r][upper_bound(edfn[r].begin(), edfn[r].end(), dfn[u])-1-edfn[r].begin()];
        if(dfn[u] < dfn[v])
        {
            int fv = e[r][upper_bound(edfn[r].begin(), edfn[r].end(), dfn[v])-1-edfn[r].begin()];
            f(dfn[u]-dfn[r]+1 + siz[fv]);
        }
        else
        {
            f(dfn[u]-dfn[r]+1);
        }
    }
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		solve();
	}
}

H题(简单构造)

\(当x为10次幂时显然无解,否则为离他最近的10次幂\)

// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
//如果在不支持 avx2 的平台上将 avx2 换成 avx 或 SSE 之一
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline ll Lsqrt(ll x) { ll L = 1,R = 2e9;while(L + 1 < R){ll M = (L+R)/2;if(M*M <= x) L = M;else R = M;}return L;}
set<ll> P;
void solve()
{
    ll x;
    cin>>x;
    ll inf = 1e18;
    if(P.find(x)!=P.end()) cout<<"-1\n";
    else 
    {
        auto it = P.lower_bound(x);
        cout<<*it<<'\n';
    }
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
    ll tmp = 1;
    P.insert(1);
    for(int i=1;i<=18;++i) {tmp = 10*tmp;P.insert(tmp);}
	int T;
	cin>>T;
	while(T--)
	{
		solve();
	}
}

D(数学)

\(原先两个式子经过简单推导后(真的很简单)可变成 x^3 =a_i^2a_j , y^3 =a_j^2a_i ,我们考虑x,y,a_i,a_j质因数分解,假设对于某个质数p,四个数分解出的质数分别x_p,y_p,\)
\((a_i)_p,(a_j)_p,那么有3*x_p = 2*(a_i)_p+(a_j)_p和3*y_p = 1*(a_i)_p+2*(a_j)_p。注意到等式左边mod3 = 0 所以解这个式子最后得到(a_i)_p = (a_j)_p(mod3),也\)
\(就是说有价值的i,j对他们质因数分解后得到的次幂在mod3意义下每个数字相等,那么我们对于每个输入的x = p ^ 3*s,用x除去最大的这个数可以看作x的质因数分解后在mod3下的的唯一合法表示\)


#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
// inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline ll Lsqrt(ll x) { ll L = 1,R = 2e9;while(L + 1 < R){ll M = (L+R)/2;if(M*M <= x) L = M;else R = M;}return L;}

#define N 50005
int n, x;
unordered_map<int,int> mp;
void solve()
{
    cin>>n;
    mp.clear();
    ll ans = 0;
    for(int i=1;i<=n;++i)
    {
        cin>>x;
        int p = pow(x,1.0/3);
        p ++;
        for( ;p ; --p)
        {
            int p3 = p*p*p;
            if(x % p3) continue;
            ans += mp[x / p3];
            ++mp[x / p3];
            break;
        }
    }
    cout<<ans<<'\n';

}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		solve();
	}
}

J(找规律)

\(显然考虑重合边当且仅当为中线,否则对于与X轴垂直坐标为x来说寻找Y轴坐标为x或A-x(排除四等分),或者是X轴为2\times x,A-x,Y轴同理\)

// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
//如果在不支持 avx2 的平台上将 avx2 换成 avx 或 SSE 之一
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline ll Lsqrt(ll x) { ll L = 1,R = 2e9;while(L + 1 < R){ll M = (L+R)/2;if(M*M <= x) L = M;else R = M;}return L;}

int n;
map<int,int> mpx,mpy;

void solve()
{
    cin>>n;
    int xs,ys,xe,ye;
    cin>>xs>>ys>>xe>>ye;
    int A = xe-xs;
    bool ok=false;
    for(int i=1;i<=n;++i)
    {
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        x1-=xs; y1-=ys;
        x2-=xs; y2-=ys;
        if(x1==x2) 
        {
            if(x1*2==A && mpx.find(x1) != mpx.end()) 
            {
                cout<<mpx[x1]<<' '<<i<<'\n';
                ok = true;
                break; 
            }
            mpx[x1]=i;
        }
        else if(y1==y2) 
        {
            if(y1*2==A && mpy.find(y1) != mpy.end()) 
            {
                cout<<mpy[y1]<<' '<<i<<'\n';
                ok = true;
                break; 
            }
            mpy[y1]=i;
        }
    }
    if(ok) return;
    for(auto &&[x,i]:mpx)
    {
        if(2*x == A) continue;
        if(mpy.find(x) != mpy.end()) {cout<<i<<' '<<mpy[x]<<'\n'; return;}
        if(mpy.find(A-x) != mpy.end()) {cout<<i<<' '<<mpy[A-x]<<'\n'; return;}
        if(mpx.find(2*x) != mpx.end() && 3*x != A) {cout<<i<<' '<<mpx[2*x]<<'\n'; return;}
        if(mpx.find(A-x) != mpx.end() && 3*x != A) {cout<<i<<' '<<mpx[A-x]<<'\n'; return;}
    }
    for(auto &&[y,i]:mpy)
    {
        if(2*y == A) continue;
        if(mpy.find(2*y) != mpy.end() && 3*y != A) {cout<<i<<' '<<mpy[2*y]<<'\n'; return;}
        if(mpy.find(A-y) != mpy.end() && 3*y != A) {cout<<i<<' '<<mpy[A-y]<<'\n'; return;}
    }
    cout<<"-1 -1\n";
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T=1;
	// cin>>T;
	while(T--)
	{
		solve();
	}
}

L(不好想的构造)

\(奇数没有,偶数可以,直接贴图,借鉴自O_start\)

class Node:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def solve():
    t = int(input())  # 读取测试用例的数量
    for _ in range(t):
        n = int(input())  # 读取每个测试用例的多边形顶点数
        
        # 如果 n 是奇数,直接输出 -1
        if n % 2 != 0:
            print("-1")
        else:
            # 如果 n == 4,直接输出正方形的坐标
            if n == 4:
                print(f"0 0")
                print(f"0 1")
                print(f"1 1")
                print(f"1 0")
            else:
                # 如果 n 是 4 的倍数
                if n % 4 == 0:
                    tmp = Node(0, 0)
                    print(f"{tmp.x} {tmp.y}")
                    tmp.x += 2
                    tmp.y -= 1
                    print(f"{tmp.x} {tmp.y}")
                    for i in range(2, n // 2):
                        if i % 2 != 0:
                            tmp.x += 1
                            tmp.y -= 2
                        else:
                            tmp.x -= 1
                            tmp.y -= 2
                        print(f"{tmp.x} {tmp.y}")
                    
                    tmp.x -= 2
                    tmp.y += 1
                    print(f"{tmp.x} {tmp.y}")
                    
                    tmp.x -= 2
                    tmp.y -= 1
                    print(f"{tmp.x} {tmp.y}")
                    
                    for i in range(2, n // 2):
                        if i % 2 != 0:
                            tmp.x += 1
                            tmp.y += 2
                        else:
                            tmp.x -= 1
                            tmp.y += 2
                        print(f"{tmp.x} {tmp.y}")
                # 如果 n 不是 4 的倍数但仍为偶数
                else:
                    tmp = Node(0, 0)
                    print(f"{tmp.x} {tmp.y}")
                    for i in range(1, n // 2):
                        if i % 2 != 0:
                            tmp.x -= 1
                            tmp.y -= 2
                        else:
                            tmp.x += 1
                            tmp.y -= 2
                        print(f"{tmp.x} {tmp.y}")
                    
                    tmp.x -= 2
                    tmp.y -= 1
                    print(f"{tmp.x} {tmp.y}")
                    
                    for i in range(1, n // 2):
                        if i % 2 != 0:
                            tmp.x -= 1
                            tmp.y += 2
                        else:
                            tmp.x += 1
                            tmp.y += 2
                        print(f"{tmp.x} {tmp.y}")

# 调用解决函数
solve()
posted @ 2024-10-16 22:26  DP_PTSD  阅读(10)  评论(0编辑  收藏  举报