2020JSCPC 部分题解

记一记训练录吧 - - 打的不是很好 配合还有欠缺
C. Cats
题意: 给你一个n 代表有n个猫房,每个猫房,每个猫房的高度处于1到20之间,现在要我们给出一种n个房间高度的构造,满足任意两个相等高度的猫房之间的最小值要低于此高度 ,而且相同高度的猫房不能相邻 emmmm 体会下样例吧 (虽然样例很水)
在这里插入图片描述
那么我们要做的是对于任意相等的高度 中间的最小值不能大于等于这个高度 ,那么顿生一悟,如果按照1–20轮流插入,比如先安排1,1的两边安排2,每个2的两边安排3,同理 下去 ,会发现这种构造是很妙也很满足式子的,那么顶多构造2^0 一直 到2^19 必然满足题意的n 然后就开始模拟上述过程,两个队列模拟就完事 。

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define ull unsigned long long
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define endl "\n"
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 4e5 + 10;
const int maxm = 1e4 + 50;
const double eps = 1e-7;
const ll inf = 0x3f3f3f3f;
const ll  lnf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;

int main()
{
    int n;
    scanf("%d",&n);
    int xx=1;
    int res=0;
    for(int i=1;i<=20;i++)
    {
        xx*=2;
        if(xx<=n)res++;
    }

    res++;
    queue<int>a,b;
    a.push(1);
    int rt=0;
    for(int i=2;i<=res;i++)
    {

        if(rt==0)
        {
            b.push(i);
            while(!a.empty())
            {
                int tem=a.front();
                b.push(tem);
                a.pop();
                b.push(i);
            }
        }else
        {
            a.push(i);
            while(!b.empty())
            {
                int tem=b.front();
                a.push(tem);
                b.pop();
                a.push(i);
            }
        }
        rt^=1;
    }
    for(int i=1;i<=n;i++)
    {
        if(rt==1)
        {
            printf("%d ",b.front());
            b.pop();
        }else
        {
            printf("%d ",a.front());
            a.pop();
        }

    }
    return 0;
}
 

D题 Delete Prime
题意:对于一个序列 1–n 我们有一种拿取规则 构造出数组D【】
每次拿走第一个数和 下标为质数的数依次放入D数组中,然后原序列重新排列也就是接上去被拿的地方,然后重新依照上述规则取值放入D数组,直到被拿完,现在有T组询问,每次有两种操作中的一种,给出n,k
操作1询问在D数组中满足D[X]等于k 的X 是多少
操作2询问在D数组中第K个数是多少 (n,k范围1e6)
不难发现不论n多大,数字在第几轮操作中被拿取是固定的,那么我们先预处理一个表,表示第i轮拿走的第p个数是num ,然后对于上述询问,直接枚举轮数,二分查找就OK


#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define ull unsigned long long
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define endl "\n"
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e6 + 10;
const int maxm = 1e4 + 50;
const double eps = 1e-7;
const ll inf = 0x3f3f3f3f;
const ll  lnf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
vector<int>v,ans;
int spr[maxn],cnt=0,vis[maxn];



void ol()//筛选素数,一定要记住素数的最大范围vis[i]=1代表是素数
{
    ms(vis, 1);
    vis[0] = vis[1] = 0;
    for (int i = 2; i < maxn; i++)
    {
        //q.push(i);
        if (vis[i])spr[cnt++] = i;
        for (ll j = 0; i * spr[j] < maxn && j < cnt; j++)
        {
            vis[i * spr[j]] = 0;
            if (i % spr[j] == 0)break;
        }
    }
}

vector<int>vec[200];
queue<int>q,p;
map<int,int>mp;
int main()
{
    ol();
    //printf("size %d\n",q.size());
    for(int i=1; i<=1000000; i++)q.push(i);
    int rt=0;
    int cnt=0;
    int cen=1;
    while(1)
    {
        if(q.size()==0&&p.size()==0)break;
        cnt++;
        if(rt==0)
        {
            int tem=q.front();
            q.pop();
            if(cnt==1||vis[cnt])
            {
                // printf("Q%d %d\n",cnt,cen);
                vec[cen].push_back(tem);
                mp[tem]=cen;
            }
            else
            {
                p.push(tem);
            }
            if(q.size()==0)
            {
                rt=1;
                cen++;
                cnt=0;
            }
        }
        else
        {
            int tem=p.front();
            p.pop();
            if(cnt==1||vis[cnt])
            {
                //printf("W%d %d\n",cnt,cen);
                vec[cen].push_back(tem);
                mp[tem]=cen;
            }
            else
            {
                q.push(tem);
            }
            if(p.size()==0)
            {
                rt=0;
                cen++;
                cnt=0;
            }
        }
        
    }
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int op;
        int n;
        int k;
        scanf("%d%d%d",&op,&n,&k);

        if(op==1)
        {
            int ans=0;
            for(int i=1; i<=cen; i++)
            {
                int pos=lower_bound(vec[i].begin(),vec[i].end(),k)-vec[i].begin();
                int pos_s=pos+1;
                if(vec[i][pos]!=k)
                {
                    int pp=lower_bound(vec[i].begin(),vec[i].end(),n)-vec[i].begin();
                    int pp_s=pp+1;
                    // ans=ans+pos-1;
                    if(vec[i][pp]!=n)
                    {
                        ans=ans+(pp_s-1);
                    }
                    else
                    {
                        ans=ans+pp_s;
                    }
                    continue;
                }
                else
                {
                    ans=ans+pos_s;
                    break;
                }
            }
            printf("%d\n",ans);
            continue;

        }

        else
        {
            int ans=0;
           // k--;
            // int befor;
            for(int i=1; i<=cen; i++)
            {
                // befor=ans;
                int pos=lower_bound(vec[i].begin(),vec[i].end(),n)-vec[i].begin();
                int pos_s=pos+1;
                int rnm;
                if(vec[i][pos]!=n)
                {
                    //  k=k-(pos-1);
                    rnm=pos_s-1;
                }
                else
                {
// k=k-pos;
                    rnm=pos_s;
                }
                if(k<=rnm)
                {
//k=k+rnm;

                    printf("%d\n",vec[i][k-1]);
                    break;
                }
                else
                {
                    k=k-rnm;

                }

            }



        }





    }




}

J题 Just Multiplicative Inverse
题意就是 质数p 然后还有一个F(x,p) 递归函数
在这里插入图片描述
x的取值范围是1到p-1 现在要我们求给定n p 的期望
其实不难发现 根据样例,每个F(x,p)的贡献就是它可以执行的递归的轮数,最终只需要把1到p-1 的总轮数求和 除p-1 就是答案,由于p是1e6的范围,递归F(x,p) 直接搞会超时,加个记忆化就OK


#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define ull unsigned long long
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define endl "\n"
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e6 + 10;
const int maxm = 1e4 + 50;
const double eps = 1e-7;
const ll inf = 0x3f3f3f3f;
const ll  lnf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int res=0;
int dp[101][maxn];
int f(int x,int p,int num)
{
    if(dp[num][x])return res=res+dp[num][x];
    res++;
    if(x<=1)
        return dp[num][x]=res;
  //  else
  return dp[num][x]=f(p%x,p,num);
    //    return -(p/x)*%p;
}




int main()
{    int t;
     scanf("%d",&t);
    while(t--){
    int p;
    scanf("%d",&p);
    int sum=0;
    int ans=0;
    int ma=0;
    for(int i=1;i<=p-1;i++)
    {
        res=0;
       sum+=f(i,p,t);
    }
    printf("%.10lf\n",sum*1.0/(p-1));
    }

}


G Grid Coloring
题意 给我们一个n*m的矩阵,定义相邻三个块颜色相同则该图形是不好的

在这里插入图片描述
现在给我们n ,m 求好的方案数并且%mod 基操
没啥好讲的,这种必然是规律题,不妨写个暴力代码打表观察下
(默认大家都打出表了)
显然显然显然以后我们特判把情况筛掉了后,只剩下n=1,2,3 范围下的数据,然后又可以打表显然的发现是成斐波那契数列分布,那就很显然了,1e9,直接上矩阵快速幂 ,完事

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int mod = 1e9+7;
int N;
ll base[10][10],ans[10][10],t[10][10];
void timea()
{
   for(int i=1;i<=N;i++)
    for(int j=1;j<=N;j++)
       t[i][j]=ans[i][j],ans[i][j]=0;

   for(int i=1;i<=N;i++)
    for(int j=1;j<=N;j++)
     for(int k=1;k<=N;k++)
      ans[i][j]=(ans[i][j]+(t[i][k]*base[k][j]%mod))%mod;
}
void timeb()
{
    for(int i=1;i<=N;i++)
     for(int j=1;j<=N;j++)
       t[i][j]=base[i][j],base[i][j]=0;

   for(int i=1;i<=N;i++)
    for(int j=1;j<=N;j++)
     for(int k=1;k<=N;k++)
      base[i][j]=(base[i][j]+(t[k][j]*t[i][k]%mod))%mod;
}
void qpow(ll b)
{
    while(b)
    {
        if(b&1)
            timea();
        timeb();
        b>>=1;
    }
}
int T;
ll n,m;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        if(n>=5) puts("8");
        else if(n==4)
        {
            if(m==4)
                puts("18");
            else puts("14");
        }
        else if(n==1)
        {
            N=2;
            base[1][1]=ans[1][1]=1;
            base[1][2]=ans[1][2]=1;
            base[2][1]=ans[2][1]=1;
            base[2][2]=ans[2][2]=0;
            qpow(m-1);
            printf("%lld\n",(2*ans[1][1])%mod);
        }
        else if(n==2)
        {
            N=2;
            base[1][1]=ans[1][1]=1;
            base[1][2]=ans[1][2]=1;
            base[2][1]=ans[2][1]=1;
            base[2][2]=ans[2][2]=0;
            qpow(m-1);
            ll ret=(2*ans[1][1])%mod;
            printf("%lld\n",(ret*ret)%mod);    //    1  2   3  5   8
        }
        else if(n==3)
        {
            if(m==3){
                puts("32");
                continue;
            }
            else if(m==4)
            {
                puts("44");
                continue;
            }
            else if(m==5)
            {
                puts("64");
                continue;
            }
            N=2;
            base[1][1]=ans[1][1]=1;
            base[1][2]=ans[1][2]=1;
            base[2][1]=ans[2][1]=1;
            base[2][2]=ans[2][2]=0;
            qpow(m-6);
            ll ret=ans[1][1]*60+ans[1][2]*40;
            printf("%lld\n",(ret+4)%mod);
        }
    }
    return 0;
}
//2 4 6 10 16   
// 4   

H Happy Morse Code
题意: 给了我们n个长度不超过5的字符串,格式为 字母-01字符串
再给我们一个母串,现在询问可以由上述n个字符串组合成母串并且各不相同的方案数,无解就输出xxxxx 按题意搞吧,有解还要判断有多少个解 xxxxx
线性dp 听队友是这么搞的 emmmmm

#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
#define pb(x) push_back(x)
using namespace std;
const int maxn = 1e5 + 10;
const int maxm = 1e4 + 50;
const ll inf = 0x3f3f3f3f;
const ll  lnf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;

map<string,int>mp;
string str;
string b[30];
int dp[maxn],fl[maxn],one[maxn];

int main()
{
    int _;
    cin>>_;
    while(_--)
    {
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++)dp[i]=one[i]=fl[i]=0;
        for(int i=1;i<=m;i++)
        {
            string a;
            cin>>a>>b[i];
        }
        cin>>str;
        dp[0]=1,fl[0]=1,one[0]=1;
        for(int i=0;i<n;i++)
        {
            //dp[i]=dp[i-1];
            for(int j=1;j<=m;j++)
            {
                if(b[j].size()+i>n)continue;
                if(str.substr(i,b[j].size())==b[j])
                {
                    //print1;
                    dp[i+b[j].size()]+=dp[i];
                    dp[i+b[j].size()]%=128;
                    fl[i+b[j].size()]+=fl[i];
                }
                fl[i+b[j].size()]=min(10,fl[i+b[j].size()]);

            }
        }
        //for(int i=0;i<=n;i++)
          //  cout<<dp[i]<<" ";
        //cout<< str.substr(0,2)<<" ";
        if(fl[n]==0)
        {
            cout<<"nonono"<<endl;
        }else
        {
            if(fl[n]==1)
                cout<<"happymorsecode"<<endl;
            else
                cout<<"puppymousecat "<<dp[n]%128<<endl;
        }
    }
}

或许能在江苏苟到一块银牌?

在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值