WY模拟赛2

模拟赛2

说实话,T1的题意理解属实搞心态。

T1

HDU-4857

题意对我这种语文能力不强的蒟蒻确实造成巨大的冲击。

简述题中的排序

在满足祖辈关系的情况下,先考虑序号最小的,让序号最小的放在能放的最前面的位置,然后再考虑第二小的,以此类推。

解法

比较显然的部分是拓扑排序,入度为 $ 0 $ 的节点一定是问题的突破口。

尝试直接从祖宗开始推,发现一个节点所能被表示的深度不唯一,并不方便其在答案序列里位置的确定。于是一个非常合理的想法就出现在脑子里,倒着来试一下。就酱紫,反向存图,如果从小的位置编号开始赋值会发现并不好做,那就尝试从大的赋值。可以发现,在反向存图的情况下,入度为 $ 0 $ 的就是当前考虑赋值的节点,显然是这些节点中最大的被附上当前所剩空位置的最大编号,但同时这是一个动态的过程,当有新节点的入度为 $ 0 $ 时要及时加入,并维护节点最大值,一个优先队列解决。

#ifdef ONLINE_JUDGE 
#else 
#define Qiu_Cheng 
#endif 
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef longlong ll; 
const int N=5e5+5,M=1e6+520,mod=1e9+7;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n,m,rd[N],ans[N];
vector<int>g[N];
fuck void solve()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)rd[i]=0,g[i].clear();
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        rd[x]++;g[y].push_back(x);
    }
    priority_queue<int>q;
    for(int i=1;i<=n;i++)if(!rd[i])q.push(i);
    int cnt=n;
    while(!q.empty())
    {
        int u=q.top();q.pop();
        ans[cnt--]=u;
        for(auto v:g[u])
        {
            rd[v]--;
            if(!rd[v])q.push(v);
        }
    }
    for(int i=1;i<=n;i++)write(ans[i]),cout<<" ";
    cout<<"\n";
}
signed main() 
{ 
#ifdef Qiu_Cheng 
    freopen("1.in","r",stdin); 
    freopen("1.out","w",stdout); 
#endif 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    int QwQ=read();
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

T2

HDU-5147

一个分治的思想,一个四元组的性质可以拆解为两个同等性质的二元组,即 $ (i,j) $ 满足 $ A_{i} < A_{j} $ 。此时考虑枚举第一个二元组的第二个键值,答案即是第 $ j $ 个之前比其小的数记为 $ m1 $ ,第 $ j+1 $ 到 $ n $ 所能组成的二元组记为 $ m2 $ ,然后
该位置对答案的贡献就可以得出为 $ m1 \times m2 $ ,最后从 $ 1 $ 到 $ n $ 累加一下贡献即可。

维护 $ m1,m2 $ 的信息则选择用树状数组实现,先正序处理比 $ j $ 位置值小的数的个数得到 $ m1 $ ,然后倒序扫一遍维护出比 $ j $ 大的数,在做一遍后缀和则可以得到 $ m2 $ 。

#ifdef ONLINE_JUDGE 
#else 
#define Qiu_Cheng 
#endif 
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef longlong ll; 
const int N=5e5+5,M=1e6+520,mod=1e9+7;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int tr[N];
#define lbit(x) x&(-x)
fuck void add(int x){while(x<N)tr[x]+=1,x+=lbit(x);}
fuck int sum(int x){int res=0;while(x){res+=tr[x];x-=lbit(x);}return res;}
int m1[N],m2[N],a[N],n;
fuck void solve()
{
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    memset(tr,0,sizeof(tr));for(int i=1;i<=n;i++){m1[i]=sum(a[i]);add(a[i]);}
    memset(tr,0,sizeof(tr));for(int i=n;i>=1;i--){m2[i]=sum(n)-sum(a[i]-1);add(a[i]);}
    int ans=0;m2[n+1]=0;
    for(int i=n;i>=1;i--)m2[i]+=m2[i+1];
    for(int i=1;i<=n;i++) ans+=(1ll*m1[i]*m2[i+1]);
    write(ans);cout<<"\n";
}
signed main() 
{ 
#ifdef Qiu_Cheng 
    freopen("1.in","r",stdin); 
    freopen("1.out","w",stdout); 
#endif 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    int QwQ=read();
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

T3

HDU-4909

考虑一个状态压缩的思想,将 $ 26 $ 个字母出现次数的奇偶性压成一个 $ 26 $ 位的 $ 01 $ 串,具体地维护一个 $ mark $ 数组,下标为当前所压的转态,储存为状态出现的次数,定义如下规则:

  1. 对于当前出现次数为偶数的字母,则对应的位置为 $ 0 $ ;
  2. 对于当前出现次数为奇数的字母,则对应的位置为 $ 1 $ ;

先不考虑 ? ,每次按顺序扫一遍字符串,异或改变该位字符的奇偶性。这个时候就能发现一个非常有用的性质,如果该串的转态出现过,则对于前面出现的该状态,每个字符一定是又出现偶数次, $ because:奇+偶=奇,偶+偶=偶 $ 。这样我们在扫描字符串时,更新状态的同时直接处理答案即可。

再考虑 ? 的情况,以 ? 为断点,暴戾得将 ? 改为 $ a到z $ ,并将对应字母的位置取反,计算答案增量并累加上即可。

注意!!!

  1. 由于 $ mark $ 数组很大,所以只对使用过的清空,不然会 TLE
  2. 千万要把 #define int long long 关闭,不然会 MLE
#ifdef ONLINE_JUDGE 
#else 
#define Qiu_Cheng 
#endif 
#include <bits/stdc++.h> 
#define i8  __int128
// #define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef longlong ll; 
const int N=2e4+5,M=1e6+520,mod=1e9+7;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int mark[(1<<26)+10];
int sum[N];//前缀异或值
fuck void solve()
{
    string s;cin>>s;s=' '+s;
    int tot=0,pos=-1,ans=0;
    sum[0]=0;mark[sum[0]]=1;
    // cout<<"aaaaaaaaaaaaaaaaa"<<endl;
    for(int i=1;i<s.size();i++)
    {
        if(s[i]=='?')
        {
            pos=i;ans+=mark[sum[tot]];
            mark[sum[tot]]++;
            continue;
        }
        tot++;
        sum[tot]=sum[tot-1]^(1<<(s[i]-'a'));
        ans+=mark[sum[tot]];
        mark[sum[tot]]++;
    }
    for(int i=0;i<=tot;i++)mark[sum[i]]=0;
    if(pos==-1){write(ans);cout<<"\n";return;}
    sum[0]=0,mark[sum[0]]=1,tot=0;
    for(int i=1;i<pos;i++)tot++,sum[tot]=sum[tot-1]^(1<<(s[i]-'a')),mark[sum[tot]]++;
    for(int i='a';i<='z';i++)ans+=(mark[sum[tot]^(1<<(i-'a'))]);
    for(int i=pos+1;i<s.size();i++)
    {
        tot++,sum[tot]=sum[tot-1]^(1<<(s[i]-'a'));
        for(int j='a';j<='z';j++)ans+=(mark[sum[tot]^(1<<(j-'a'))]);
    }
    for(int i=0;i<=tot;i++)mark[sum[i]]=0;
    write(ans),cout<<"\n";
}
signed main() 
{ 
#ifdef Qiu_Cheng 
    freopen("1.in","r",stdin); 
    freopen("1.out","w",stdout); 
#endif 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    int QwQ=read();
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

T4

#ifdef ONLINE_JUDGE 
#else 
#define Qiu_Cheng 
#endif 
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef longlong ll; 
const int N=1e6+5,M=1e6+520,mod=1e9+7;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int prime[N],is_prime[N]={1,1},tot=0;
fuck void xxs()
{
    for(int i=1;i<=N;i++)is_prime[i]=0;
    for(int i=2;i<=N;i++)
    {
        if(!is_prime[i])prime[++tot]=i;
        for(int j=1;j<=tot&&i*prime[j]<=N;j++)
        {
            is_prime[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}
fuck int gsc(int a,int b,int Mod)
{
    a%=Mod,b%=Mod;
    int res=0;
    while(b)
    {
        if(b&1)res=(res+a+Mod)%Mod;
        b>>=1;a=(a+a+Mod)%Mod;
    }
    return (res+Mod)%Mod;
}
fuck int ksm(int a,int b,int Mod)
{
    int res=1;
    while(b)
    {
        if(b&1)res=gsc(res,a,Mod);
        b>>=1;a=gsc(a,a,Mod);
    }
    return (res+Mod)%Mod;
}
fuck int check(int a,int n,int x,int t)
{
    int res=ksm(a,x,n),last=res;
    for(int i=1;i<=t;i++)
    {
        res=gsc(res,res,n);
        if((res==1)&&(last!=1)&&(last!=n-1))return 1;
        last=res;
    }
    return res!=1;
}
fuck int Miller_Rabin(int n)
{
    if((n<2))return 0;
    if(n==2)return 1;
    if((n&1)==0) return 0;
    int x=n-1,t=0;
    while((x&1)==0)x>>=1,t++;
    for(int i=1;i<=20;i++)
    {
        int a=rand()%(n-1)+1;
        if(check(a,n,x,t))return 0;
    }
    return 1;
}
fuck int sq(int n){int m=sqrt(n*1.0);return m*m==n||(m-1)*(m-1)==n||(m+1)*(m+1)==n;}
fuck int isyn(int n)
{
    if(Miller_Rabin(n))return 1;
    int ti=0;int m=n;
    for(int i=1;i<=tot;i++)
    {
        if(m%prime[i]==0)
        {
            ti++;
            if(ti>=2) return 0;
            while(m%prime[i]==0)m/=prime[i];
        }
        if(m==1)return 1;
    }
    if(m!=n)return 0;
    if(sq(n))return 1;
    return 0;
}
fuck void solve()
{
    int n;
    while(n=read())
    {
        if(n==-1)break;
        if(n==1){cout<<"0"<<"\n";continue;}
        if(n!=4&&n%4==0){cout<<"1"<<"\n";continue;}
        int m=n;
        if(m%2==0)m/=2;
        if(!isyn(m)){cout<<"1"<<"\n";}
        else cout<<n-1<<"\n";
    }
    
}
signed main() 
{ 
#ifdef Qiu_Cheng 
    freopen("1.in","r",stdin); 
    freopen("1.out","w",stdout); 
#endif 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    xxs();
    // for(int i=1;i<=tot;i++)cout<<prime[i]<<"\n";
    // int QwQ=read();
    // while(QwQ--)solve(); 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666
posted @ 2025-04-23 18:19  Nightmares_oi  阅读(18)  评论(0)    收藏  举报