WY模拟赛1

模拟赛1

T1

签到题,开个豪华的map就行。

#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=1e5+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,a[N];
map<int,int>mp[N];
fuck void solve()
{
    int cnt=1;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],mp[i].clear();
    for(int i=1;i<=n;i++)
    {
        if(mp[cnt][a[i]])mp[++cnt][a[i]]=1;
        else mp[cnt][a[i]]=1;
    }
    cout<<cnt<<"\n";
}
signed main() 
{ 
    freopen("cul.in","r",stdin); 
    freopen("cul.out","w",stdout); 
    // 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

乱搞不如总司令

众所周知此题的 $ O(T) $暴力是cout<<"yes"<<"\n";

正解

很容易可以发现,所谓的数字,本质上可分为 $ A,B,C $ 三类:

\[\left\{ \begin{aligned} A:s_{i} \equiv 0 (mod 3)\\ B:s_{i} \equiv 1 (mod 3)\\ C:s_{i} \equiv 2 (mod 3) \end{aligned} \right. \]


统计出这些类型的数的个数记为 $ a_{0},a_{1},a_{2} $,现在我们需要选出 $ K $ 张,也就是分别选择 $ A,B,C $ 类型的数
$ i,j,k $ 张,满足要求(考虑到 $ a_{0} $无影响 ):

\[\left\{ \begin{aligned} i+j+k=K \\ j \times 1 + k \times 2 \equiv a_{1} \times 1 + a_{2} \times 2 ( mod 3) \end{aligned} \right. \]

这样就可以 $ k $ 和 $ j $ 然后通过 $ i=K-k-j $ 得到 $ i $,然后只要三种类型满足 $ 0 \leq i \leq a_{0} ,0 \leq j \leq a_{1},0 \leq k \leq a_{2} $,就找到了一组解。
但是这显然无法保证要求没有前导零的限制。

于是考虑贪心(对于大于零的数从后往前删,零则从前往后删一定最优)有以下三种情况:

  1. 计算第一个(s[i]-'0')%3==0 && s[i]!='0的数前的零的个数,记为 cnt ,如果 $ cnt \leq i $ ,则根据贪心答案一定为 yes
  2. 标记 f1 为第一个 $ 0 $ 前是否存在 $ mod 3 = 1 $的数,在 $ j < a_{1} $ 的前提下,如果存在 f1==1,则答案为 yes
  3. 标记 f2 为第一个 $ 0 $ 前是否存在 $ mod 3 = 2 $的数,在 $ k < a_{2} $ 的前提下,如果存在 f2==1,则答案为 yes

其余情况则为 no

#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=2e3+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,kk,a[N];
string s;
fuck void solve()
{
    cin>>n>>kk>>s;s=' '+s;memset(a,0,sizeof(a));
    for(int i=1;i<=n;i++)a[(s[i]-'0')%3]++;
    int base=(a[1]+a[2]*2)%3,f1=0,cnt=0,f2=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='0')cnt++;
        if((s[i]-'0')%3==0&&s[i]!='0')break;
    }    
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='0')break;
        if((s[i]-'0')%3==1)f1=1;
        if((s[i]-'0')%3==2)f2=1;
    }
    // cout<<base<<"\n";
    if(kk==n||((n==kk+1)&&a[0])){cout<<"yes"<<"\n";return;}
    if(kk==0){cout<<(base?"no":"yes")<<"\n";return;}
    // cout<<cnt<<" "<<f2<<" "<<f3<<"\n";
    for(int k=0;k<=a[2]&&k<=kk;k++)
    {
        for(int j=(base-(k*2)%3+3)%3;j<=a[1]&&k+j<=kk;j+=3)
        {
            int i=kk-k-j;
            // cout<<i<<" "<<j<<" "<<k<<"\n";
            if(i>=0&&i<=a[0]&&(i>=cnt||(j<a[1]&&f1)||(k<a[2]&&f2)))
            {
                cout<<"yes"<<"\n";
                return;
            }
        }
    }
    cout<<"no"<<"\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; 
}

T3

注意以下几点:

  1. 根据转换表可以预处理出每个字母转多少可以转回自己 。
  2. 很容易发现,对于一个字母转换回自己的次数最多只有6种不同的( $ 1+2+3+4+5+6+7>26 $ ) 。

这样所有的字母可以分为 $ 6 $ 类,问题同时转化为在 $ 6 $ 类次数中每种次数集合中取若干个数的所有情况,要求每个集合至少取一个,通过容斥可以轻松计算出。
最后用 $ lcm $ 处理答案即可。

#ifdef ONLINE_JUDGE 
#else 
#define Qiu_Cheng 
#endif 
#include <bits/stdc++.h> 
#define int long long 
#define fuck inline
using namespace std; 
// typedef long long ll; 
const int N=2e5+10,mod=1e9+7;
const int inf=INT_MAX,INF=0x3f3f3f; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
inline 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;
}
inline void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
#define pii pair<int,int>
#define fs first
#define se second 
vector<pii>g;
char s[30];
int vis[30],to[N];
int n;
fuck int ksm(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res=res*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return (res+mod)%mod;
}
fuck int lcm(int a,int b){return a/(__gcd(a,b))*b;}
fuck void xhj()
{
    for(int i=1;i<=26;i++)to[i]=s[i]-'a'+1;
    // for(int i=1;i<=26;i++)cout<<to[i]<<" ";
    // cout<<endl;
    // cout<<"ccccccccccccccc"<<endl;
    map<int,int>mp;memset(vis,0,sizeof(vis));g.clear();
    // cout<<"bbbbbbbbbbbbb"<<endl;
    for(int i=1;i<=26;i++)
    {
        // cout<<i<<"    dddddddddddd"<<endl;
        if(!vis[i])
        {
            vis[i]=1;int res=1,x=to[i];
            while(x!=i)vis[x]=1,res++,x=to[x];
            mp[res]++;
        }
    }
    for(auto i=mp.begin();i!=mp.end();i++)g.push_back(*i);
}
fuck int rc(vector<int>&frz,int n)
{
    int ans=0,len=frz.size();
    for(int i=1;i<(1<<len);i++)
    {
        int f=-1,sum=0,num=0;
        for(int j=0;j<len;j++)if((1<<j)&i)sum+=frz[j],num++;
        if(num%2==len%2)f=1;
        int cnt=ksm(sum,n);
        ans=(ans+((f*cnt)+mod)%mod)%mod;
    }
    return ans;
}

fuck void solve()
{   
    cin>>n;
    int ans=0;
    for(int i=1;i<=26;i++)cin>>s[i];
    // for(int i=1;i<=26;i++)cout<<s[i]<<endl;
    // cout<<"aaaaaaaaaaaaaaaaaaa"<<endl;
    xhj();
    // cout<<"bbbbbbbbbbb"<<endl;
    vector<int>frz;
    for(int i=1,end=(1<<g.size());i<end;i++)
    {
        int sum=1;frz.clear();
        for(int j=0;j<g.size();j++)
        {
            if((1<<j)&i)
            {
                sum=lcm(sum,g[j].fs);
                frz.push_back(g[j].fs*g[j].se);
            }
        }
        if(frz.size()>n)continue;
        int sum2=rc(frz,n);
        ans=(ans+sum*sum2)%mod;
    }
    cout<<ans<<"\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 QwQ=read(); 
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//12 825076913 0 173167432
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666
posted @ 2025-04-13 11:40  Nightmares_oi  阅读(24)  评论(0)    收藏  举报