2024初三年前集训测试2

0pts 遗憾离场。

我咋啥也不会。

赛后题解

比较有质量的一场,但是为啥同时是 NOIP 模拟赛和 CSP 模拟赛啊(?

T1 上海

分解 \(k\) 的质因数,如果 \(n\) 的公共质因子的个数多于 \(\frac {k_{c_i}} 2\),则满足条件。

如果最终构造的数与 \(k\) 相等,则无解。

Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e4;
const int INF=1e9;
const int maxn=0x3f3f3f3f;
int n,m,maxx,cnt,root;
int ans=1;
inline int read()
{
    int s = 0,w = 1;char ch = getchar();
    while(ch<'0'||ch>'9'){ if(ch == '-') w = -1;ch = getchar();}
    while(ch>='0'&&ch<='9'){ s = s*10+ch-'0';ch = getchar();}
    return s*w;
}
int k;
signed main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    k=read();
    m=k;
    for(int i=2;i<=sqrt(k);++i)
    {
        //cout<<i*i%k;
        int tot=0;
        for(;(k%i)==0;k/=i) ++tot;
            for(int j=1;j<=(tot+1)/2;++j) ans*=i;
    }
    ans*=k;
    if(ans==m) cout<<-1;
    else cout<<ans;
}

T2 华二

因为数字只有 1 到 9,所以考虑分类讨论。

  1. 首先 1 5 7 显然与每个数字互质,对于答案没有影响。

  2. \(a_i=2\)\(4\)\(8\) 时,与 2 的倍数的数不互质。

  3. \(a_i=3\)\(9\) 时,与 2 的倍数的数不互质。

  4. 当 \(a_i=6\) 时,特殊处理,把 6 之前的一段单独处理。

家里的傻逼输入法连正常的字符都打不出来,傻逼2345输入法.

只能用这破电脑写字了.

所以设立一个数组存上述情况的个数,然后组合数求其在序列中的答案.

Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5;
const int INF=1e9;
const int maxn=0x3f3f3f3f;
const int p=998244353;
int n,m,maxx,cnt,root;
int ans=1;
int flag[10];//flag[i]存flag[i]的倍数的个数
int a[N],js[N],inv[N];
inline int read()
{
    int s = 0,w = 1;char ch = getchar();
    while(ch<'0'||ch>'9'){ if(ch == '-') w = -1;ch = getchar();}
    while(ch>='0'&&ch<='9'){ s = s*10+ch-'0';ch = getchar();}
    return s*w;
}
inline int qpow(int a,int b)
{
    int ans=1,k=a;
    while(b>0)
    {
        if(b&1) ans=(ans*k)%p;
        k=(k*k)%p;
        b>>=1;
    }  
    return ans;
}    
inline int C(int m,int n)
{
    //cout<<js[n]*inv[m]<<inv[n-m]<<endl;
    return(((js[n]*inv[m])%p)*inv[n-m])%p;
}
signed main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    js[0]=1;
    n=100000;
    for(register int i=1;i<=n;++i)
        js[i]=js[i-1]*i%p;
    inv[n]=qpow(js[n],p-2);
    //cout<<inv[n];
    inv[0]=1;
    for(register int i=n-1;i>=1;--i)
        inv[i]=(inv[i+1]*(i+1))%p;
    //预处理逆元

    n=read();
    for(int i=1;i<=n;++i)
        a[i]=read();
    for(int i=1;i<=n;++i)
    {
        if(a[i]==1) flag[1]++;
        if(a[i]==2 || a[i]==4 || a[i]==8) flag[2]++;
        if(a[i]==3 || a[i]==9) flag[3]++;
        if(a[i]==5) flag[5]++;
        if(a[i]==7) flag[7]++;
        if(a[i]==6 || i==n) 
        {
            // cout<<flag[2];
            // cout<<flag[1]+flag[3]+flag[5]+flag[7];
            ans=ans*C(flag[2],flag[3]+flag[2])%p;
            flag[2]=flag[3]=0;
            //cout<<ans;
        }
    }
    ans=ans*C(flag[1],n-flag[5]-flag[7])%p*C(flag[5],n-flag[7])%p*C(flag[7],n)%p;
    cout<<ans;
   
}

T3 高爸

gal bar

50 pts 做法

暴力枚举每个端点为补齐的数,取 min 即可.

正解 2 分 /3 分+数据结构维护.

我用的动态开点权值线段树,每读入一个数就插入并且在建树时二分答案即可.

代码略抽象,不会动态开点可以去提高 OJ 线段树合并学习.

Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ls t[p].l
#define rs t[p].r
const int N=2e5;
const int INF=1e9;
const int p=998244353;
int n,a,b,maxx,cnt,root;
int ans,suma,sumb,cnta,cntb;
int c[N];
int tot;
struct node
{
    int l,r,num,val;
}t[N*80];
inline void push_up(int p)
{
    t[p].num=t[ls].num+t[rs].num;
    t[p].val=t[ls].val+t[rs].val;
    return;
}
inline void update(int &p,int l,int r,int pos)
{
    if(!p) p=++cnt;
    if(l==r)
    {
        t[p].val+=pos;
        t[p].num++;
        //cout<<t[p].val<<" "<<t[p].num<<endl;
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=pos) update(ls,l,mid,pos);
    else update(rs,mid+1,r,pos);
    push_up(p);
}
inline int get_dis(int p)
{
    return a*(cnta*p-suma)+b*(sumb-cntb*p);
}
inline void find(int p,int l,int r)
{
    if(l==r)
    {
        suma+=t[p].val,cnta+=t[p].num;
        cout<<get_dis(l)<<'\n';
        return;
    }
    int mid=l+r>>1;
    suma+=t[ls].val,cnta+=t[ls].num;
    sumb+=t[rs].val,cntb+=t[rs].num;
    if(get_dis(mid)>get_dis(mid+1))
    {
        sumb-=t[rs].val,cntb-=t[rs].num;
        find(rs,mid+1,r);
    }
    else
    {
        suma-=t[ls].val,cnta-=t[ls].num;
        find(ls,l,mid);
    }
    return;
}
signed main()
{
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    cin.tie(0),cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>n>>a>>b;
    for(int i=1;i<=n;++i)
        cin>>c[i];
    for(int i=1;i<=n;++i)
    {
        update(root,0,INF,c[i]);
        suma=sumb=cnta=cntb=0;
        find(root,0,INF);
    }
}

话说正好昨天开了线段树合并,结果就考了,算是押到题了吗?

T4 金牌

对于每个区间 \([l,r]\) 分情况讨论,一种是l在r的子树,一种是r在l的子树中,还有l到r既包含子树又包含简单路径,答案为 $$\sum_{i\in l} \sum_{j\in r} 2^{dis_{l,r}+dis_{i,l}+dis_{j,r}}$$

dfs 序完求 LCA 即可

要求 LCA,Tarjan 算法最优但是用树剖超级卡常也可以过,赛事仅 69pts,贺了洛天依逆天快读快写板子卡过了,但是其实是故意让卡过的因为时间限制改为了1.5s(原1s).

image

100pts Code
#include<bits/stdc++.h>
using namespace std;
const int N=2e6;
const int mod=998244353;
int n,m;
inline void fire(){freopen("data.in","r",stdin);freopen("data.out","w",stdout);}
namespace Fast_I {char *_Buf, *_Start_ptr, *_End_ptr;std::streambuf* inbuf;unsigned int Size;bool _Ok;struct Fast_Istream {operator bool(){return _Ok; }Fast_Istream(std::streambuf*, unsigned int);Fast_Istream(unsigned int);Fast_Istream(const char*, unsigned int);Fast_Istream& operator>>(char&);Fast_Istream& operator>>(char*);Fast_Istream& operator>>(bool&);Fast_Istream& operator>>(short&);Fast_Istream& operator>>(int&);Fast_Istream& operator>>(long&);Fast_Istream& operator>>(long long&);Fast_Istream& operator>>(unsigned short&);Fast_Istream& operator>>(unsigned int&);Fast_Istream& operator>>(unsigned long&);Fast_Istream& operator>>(unsigned long long&);Fast_Istream& operator>>(float&);Fast_Istream& operator>>(double&);Fast_Istream& operator>>(long double&);Fast_Istream& operator>>(std::string&);template <typename Typex>void operator()(Typex& _Val) { *this >> _Val; }template <typename Typex, typename... More>void operator()(Typex&, More&...);std::streambuf* rdbuf() { return inbuf; }void rdbuf(std::streambuf* _inbuf) { inbuf = _inbuf; }void rdbuf(const char*);void pop();char peek();};}
namespace Fast_O {std::string buf;std::streambuf* outbuf;struct Fast_Ostream {Fast_Ostream(std::streambuf*, unsigned int);Fast_Ostream(std::streambuf* out) { outbuf = out; }Fast_Ostream(const char*, unsigned int);Fast_Ostream(unsigned int);void flush();~Fast_Ostream();void endl() { buf.push_back('\n'); }template <typename Typex>void endl(const Typex& _Val);template <typename Typex, typename... More>void endl(const Typex&, const More&...);template <typename Typex>void operator()(const Typex& _Val);template <typename Typex, typename... More>void operator()(const Typex&, const More&...);Fast_Ostream& operator<<(char);Fast_Ostream& operator<<(const char*);Fast_Ostream& operator<<(const std::string&);Fast_Ostream& operator<<(bool);Fast_Ostream& operator<<(short);Fast_Ostream& operator<<(int);Fast_Ostream& operator<<(long);Fast_Ostream& operator<<(long long);Fast_Ostream& operator<<(unsigned short);Fast_Ostream& operator<<(unsigned int);Fast_Ostream& operator<<(unsigned long);Fast_Ostream& operator<<(unsigned long long);std::streambuf* rdbuf() { return outbuf; }void rdbuf(std::streambuf* _outbuf) { outbuf = _outbuf; }void rdbuf(const char*);};}
namespace Fast_IO {Fast_I::Fast_Istream fin(std::cin.rdbuf(), 1048576);Fast_O::Fast_Ostream fout(std::cout.rdbuf()); }
#define cin Fast_IO::fin
#define cout Fast_IO::fout
namespace Fast_I {Fast_Istream::Fast_Istream(std::streambuf* in, unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;inbuf = in;_Start_ptr = _End_ptr = _Buf = new char[Sz];}Fast_Istream::Fast_Istream(const char* in, unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;rdbuf(in);_Start_ptr = _End_ptr = _Buf = new char[Sz];}Fast_Istream::Fast_Istream(unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;_Start_ptr = _End_ptr = _Buf = new char[Sz];}void Fast_Istream::rdbuf(const char* File) {static std::ifstream __In__(File);rdbuf(__In__.rdbuf());}void Get_Char(char& _Val) {if (_Start_ptr == _End_ptr) {_Start_ptr = _Buf;_End_ptr = _Buf + inbuf->sgetn(_Buf, Size);}if (_Start_ptr == _End_ptr) {_Val = -1;_Ok = 0;} else {_Val = *_Start_ptr++;}}Fast_Istream& Fast_Istream::operator>>(char& _Val) {if(_Ok){Get_Char(_Val);while (_Val == 32 || _Val == 10 || _Val == 13 || _Val == 8 || _Val == 9 || _Val == 7 || _Val == 12 || _Val == 11) {Get_Char(_Val);}}return *this;}Fast_Istream& Fast_Istream::operator>>(char* _Val) {if (_Ok) {Get_Char(*_Val);while (*_Val == 32 || *_Val == 10 || *_Val == 13 || *_Val == 8 ||*_Val == 9 || *_Val == 7 || *_Val == 12 || *_Val == 11) {Get_Char(*_Val);}while (*_Val != 32 && *_Val != 10 && *_Val && *_Val != -1 && *_Val != 9 &&*_Val != 11 && *_Val != 12) {Get_Char(*++_Val);}*_Val = 0;--_Start_ptr;}return *this;}Fast_Istream& Fast_Istream::operator>>(std::string& _Val) {if (_Ok) {char c;Get_Char(c);while (c == 32 || c == 10 || c == 13 || c == 8 || c == 9 || c == 7 ||c == 12 || c == 11) {Get_Char(c);}for (_Val.clear();c != 32 && c != 10 && c && c != -1 && c != 9 && c != 11 && c != 12;Get_Char(c)) {_Val.push_back(c);}--_Start_ptr;}return *this;}template <typename Typex>void Get_Int(Typex& _Val) {if (_Ok) {char ch;bool _F = 0;for (Get_Char(ch); (ch < 48 || ch > 57) && ch != -1; Get_Char(ch)) {_F = ch == 45;}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}if (_F) {_Val = ~_Val + 1;}--_Start_ptr;}}template <typename Typex>void Get_Unsigned(Typex& _Val) {if (_Ok) {char ch;Get_Char(ch);while ((ch < 48 || ch > 57) && ch != -1) {Get_Char(ch);}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}--_Start_ptr;}}template <typename Typex>void Get_Double(Typex& _Val) {if(_Ok){char ch;bool _F = 0;for (Get_Char(ch); (ch < 48 || ch > 57) && ch != -1; Get_Char(ch)) {_F = ch == 45;}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}if (ch == 46) {unsigned long long _Pow = 1;for (Get_Char(ch); ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val += Typex((ch ^ 48) * 1.0 / (_Pow *= 10));}}if (_F) {_Val = -_Val;}--_Start_ptr;}}Fast_Istream& Fast_Istream::operator>>(bool& _Val) {if(_Ok){char ch;Get_Char(ch);while (ch == 32 || ch == 10 || ch == 13 || ch == 8 || ch == 9 || ch == 7 ||ch == 12 || ch == 11) {Get_Char(ch);}while (ch != 32 && ch != 10 && ch && ch != -1 && ch != 9 && ch != 11 &&ch != 12) {_Val |= ch != 48;Get_Char(ch);}--_Start_ptr;}return *this;}Fast_Istream& Fast_Istream::operator>>(short& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(int& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long long& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned short& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned int& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned long& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned long long& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(float& _Val) {Get_Double(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(double& _Val) {Get_Double(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long double& _Val) {Get_Double(_Val);return *this;}template <typename Typex, typename... More>void Fast_Istream::operator()(Typex& _Val, More&... _More) {*this >> _Val;operator()(_More...);}void Fast_Istream::pop() {char ch;Get_Char(ch);}char Fast_Istream::peek() {if (_Start_ptr == _End_ptr) {_Start_ptr = _Buf;_End_ptr = _Buf + inbuf->sgetn(_Buf, Size);}if (_Start_ptr == _End_ptr) {_Ok = 0;return -1;} else {return *_Start_ptr;}}}
namespace Fast_O {Fast_Ostream::Fast_Ostream(std::streambuf* out, unsigned int Size) {buf.reserve(Size);outbuf = out;}Fast_Ostream::Fast_Ostream(const char* File, unsigned int Size) {buf.reserve(Size);rdbuf(File);}void Fast_Ostream::rdbuf(const char* File) {static std::ofstream __Out__(File);rdbuf(__Out__.rdbuf());}Fast_Ostream::Fast_Ostream(unsigned int Size) {buf.reserve(Size);}void Fast_Ostream::flush() {outbuf->sputn(buf.data(), buf.size());buf.clear();}Fast_Ostream::~Fast_Ostream() {flush();}Fast_Ostream& Fast_Ostream::operator<<(char _Val) {buf.push_back(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(const char* _Val) {while (*_Val) {buf.push_back(*_Val++);}return *this;}Fast_Ostream& Fast_Ostream::operator<<(const std::string& _Val) {for (auto&& i : _Val) {buf.push_back(i);}return *this;}template <typename Typex>void Put_Unsigned(Typex _Val) {char* _Stack = (char*)malloc(sizeof(Typex) * 3);unsigned S_top = 0;while (_Val) {_Stack[++S_top] = (_Val % 10) ^ 48;_Val /= 10;}if (!S_top) {buf.push_back('0');}while (S_top) {buf.push_back(_Stack[S_top--]);}free(_Stack);}void Put_Int(long long _Val) {if (_Val < 0) {buf.push_back('-');Put_Unsigned(~_Val + 1);} else {Put_Unsigned(_Val);}}Fast_Ostream& Fast_Ostream::operator<<(bool _Val) {buf.push_back(_Val ? '1' : '0');return *this;}Fast_Ostream& Fast_Ostream::operator<<(short _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(int _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(long _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(long long _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned short _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned int _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned long _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned long long _Val) {Put_Unsigned(_Val);return *this;}template <typename Typex>void Fast_Ostream::endl(const Typex& _Val) {*this << _Val << '\n';}template <typename Typex, typename... More>void Fast_Ostream::endl(const Typex& _Val, const More&... _More) {*this << _Val;endl(_More...);}template <typename Typex>void Fast_Ostream::operator()(const Typex& _Val) {*this << _Val;}template <typename Typex, typename... More>void Fast_Ostream::operator()(const Typex& _Val, const More&... _More) {*this << _Val;operator()(_More...);}}
#define int long long
struct node
{
    int next,to,v;
}e[N<<1];
int head[N],cnt,f[N],tot;
int P[N];
int fa[N],deep[N],size[N],son[N],rk[N],top[N],id[N];
int p[N][21],d[N],height[N];
int g[N];
inline void add(int u,int v)
{
    e[++cnt].next=head[u];
    e[cnt].to=v;
    head[u]=cnt;
}
inline void dfs1(int x)
{
    d[x]=size[x]=1;
    deep[x]=deep[fa[x]]+1;
    for(int i=head[x];i;i=e[i].next)
    {
        int y=e[i].to;
        if(y==fa[x]) continue;
        fa[y]=x,dfs1(y);
        d[x]+=(d[y]<<1);
        size[x]+=size[y];
        if(size[y]>size[height[x]]) height[x]=y;
    }
    d[x]%=mod;
}
inline int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    return x;
}
inline int get_fa(int x,int y)
{
    while(deep[top[x]]>deep[y]+1) x=fa[top[x]];
    return (top[x]==top[y])?height[y]:top[x];
}
void dfs2(int x)
{
    g[x]=d[x]+(fa[x]?((g[fa[x]]-(d[x]<<1))<<1):0),g[x]%=mod;
    for(int i=head[x];i;i=e[i].next)
    {
        int y=e[i].to;
        if(y==fa[x]) continue;
        top[y]=(y==height[x])?top[x]:y,
        dfs2(y);
    }
    return ;
}
signed main()
{
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    int root=1;
    cin(n);
    P[0]=1;
    for(int i=1;i<=n;++i)
        P[i]=(P[i-1]<<1)%mod;
    for(int i=1;i<n;++i)
    {
        int u,v;
        cin(u,v);
        add(u,v);
        add(v,u);
    }
    dfs1(root);
    top[root]=root;
    dfs2(root);
    cin(m);  
    while(m--)
    {
        int x,y,lva;
        cin(x,y);
        lva=lca(x,y);
        if(deep[x]>deep[y]) swap(x,y);
        if(x!=lva)
        cout((d[y]*d[x])%mod*P[deep[x]+deep[y]-(deep[lva]<<1)]%mod,"\n");
        else
        {
            int k=get_fa(y,x);
            cout((d[y]*(g[x]-(d[k]<<1))%mod*P[deep[x]+deep[y]-(deep[lva]<<1)]%mod+mod)%mod,'\n');
        }
    }
}

最后 369 pts,怎么是 rk1 ???

image

其实主要是沾了昨天开线段树合并的光,蒟蒻等着下次被众神犇爆踩QAQ

今天闲话先不写了因为这 B 键盘太好用了,乐.

posted @ 2024-02-02 12:02  HS_xh  阅读(102)  评论(14编辑  收藏  举报
init();