• 2017/10/11模拟赛


    学者(scholar)

    【题目描述】

    翠江城有一位可敬的学者,这一天你跟随着小C去拜访他。然而在会客厅,小C却把你撂在一旁,自己跟学者谈笑风生。你难免会有些不满。学者也注意到了你,他决定给你一些事做。学者家里有n本书籍,从1~n标号,而且这些书籍都有一种奇妙的特性:如果两本书的标号的最大公因数大于1,那么这两本书就含有相关的内容。其中标号为质数的书籍为重要书籍。学者要求你从中找出一套包含至少一本重要书籍的互不相关的书籍。你听了头皮发麻,随手抽了k本互不相关的书籍,竟然满足了要求。你就很好奇,k最小是多少一定可以满足学者的需求呢?

    【输入数据】

    输入第一行一个正整数T,表示数据组数。

    接下来T行,每行一个正整数n,表示学者家的藏书量。

    【输出数据】

    输出T行,每行一个整数,表示对于每个n,最小的k,对于无解的情况,输出-1

    【样例输入】

        1

       8

    【样例输出】

        3

    【数据范围】

    对于10%的数据,T,n<=5;

    对于20%的数据,T,n<=1000;

    对于50%的数据,n<=10^9;

    另外20%的数据,T=1;

    对于100%的数据,1<=T<=10^5,1<=n<=10^14。

    【样例解释】

    所有3元互不相关的书籍集合为:

    {1,2,3},{1,2,5},{1,2,7},{1,3,4},{1,3,5},{1,3,7},{1,3,8},{1,4,5},

    {1,4,7},{1,5,6},{1,5,7},{1,5,8},{1,6,7},{1,7,8},{2,3,5},{2,3,7},

    {2,5,7},{3,4,5},{3,4,7},{3,5,7},{3,5,8},{3,7,8},{4,5,7},{5,6,7},

    {5,7,8},其中每个集合都包含一本重要书籍。

    题意:求最小的k满足1~n中任意k个互质的数组成的集合中都至少有一个质数,多次询问。

    题解:为了求出最小k,我们要尽量构造1~n最大的不含质数的互质子集,显然把1和每个质数平方丢进去即可,所以我们只要求出sqrt(n)内质数个数x,x+2即为答案。先预处理出1~10^7内所有质数,二分查询质数即可。

    代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #define MN 10000000
     5 using namespace std;
     6 int T,ans,cnt,pr[664580];
     7 long long n;
     8 bool vis[MN+5];
     9 void shai(){
    10     for(int i=2;i<=MN;i++)
    11         if(!vis[i]){
    12             pr[++cnt]=i;
    13             for(int j=2;j*i<=MN;j++) vis[i*j]=1;
    14         }
    15 }
    16 int main(){
    17     freopen("scholar.in","r",stdin);
    18     freopen("scholar.out","w",stdout);
    19     scanf("%d",&T); shai();
    20     while(T--){
    21         scanf("%lld",&n);
    22         if(n==1){printf("-1
    ");continue;}
    23         n=sqrt(n);
    24         int l=0,r=664580,ans;
    25         while(l<=r){
    26             int mid=(l+r)>>1;
    27             if(pr[mid]<=n) l=mid+1,ans=mid;
    28             if(pr[mid]>n) r=mid-1;
    29         }
    30         printf("%d
    ",ans+2);
    31     }
    32     return 0;
    33 }

    主持人(anchorman)

    【题目描述】

    小W是这次献祭的主持人。为了举行献祭,他先亲自去掀翻小C的棋盘,所以他就把布置场地的任务交给了你。有一片N行M列的网格土地,每一格都有一个XY值cij。你需要挑选出其中一块A行B列的土地作为献祭场地。我们定义一块土地的不稳定度为这块土地中最大的XY值和最小的XY值的差,为了保持均衡,要求挑选的场地的不稳定度尽可能小。小W希望你求出这个最小值,并统计有多少块场地满足这个最小值。

    【输入数据】

    第一行四个正整数N,M,A,B。

    接下来N行,每行M个整数,表示一个XY值矩阵。

    【输出数据】

    输出一行两个整数,用空格隔开,表示选择的场地中最小的不稳定度和满足最小值的场地数。

    【样例输入】

    2 3 1 2

    1 3 2

    1 4 2

    【样例输出】

    1 1

    【数据范围】

    对于10%的数据,N,M<=10;

    对于30%的数据,N,M<=100;

    对于50%的数据,N,M<=500;

    另外10%的数据,0<=cij<=1;

    另外10%的数据,|cij|<=5;

    对于100%的数据,1<=N,M,A,B<=1000,A<=N,B<=M,

    |cij|<=10^9。

    【样例解释】

    选择土地(1,2)~(1,3),最大为3,最小为2,相差为1。

    题解(暴力):我们可以想到如果强行枚举n,m,A,B的话,复杂度为O(n^4),那么,如果我们先预处理出横向的情况并缩点,然后在枚举纵向的,2次的复杂度都为O(n^3/8)。似乎有90分。

    代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define MN 1005
     5 using namespace std;
     6 int n,m,A,B,a[MN][MN],b[MN][MN],c[MN][MN],ans=1e9,cnt;
     7 int main()
     8 {
     9     freopen("anchorman.in","r",stdin);
    10     freopen("anchorman.out","w",stdout);
    11     scanf("%d%d%d%d",&n,&m,&A,&B);
    12     for(int i=1;i<=n;i++)
    13         for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
    14     memset(b,127,sizeof(b));memset(c,0,sizeof(c));
    15     for(int i=1;i<=n;i++)
    16         for(int j=1;j<=m-B+1;j++)
    17             for(int k=j;k<=j+B-1;k++){
    18                 b[i][j]=min(b[i][j],a[i][k]);
    19                 c[i][j]=max(c[i][j],a[i][k]);
    20             }
    21     for(int j=1;j<=m-B+1;j++)
    22         for(int i=1;i<=n-A+1;i++){
    23             int maxn=0,minn=1e9;
    24             for(int k=i;k<=i+A-1;k++){
    25                 minn=min(minn,b[k][j]);
    26                 maxn=max(maxn,c[k][j]);
    27             }
    28             ans=min(ans,maxn-minn);
    29         }
    30     for(int j=1;j<=m-B+1;j++)
    31         for(int i=1;i<=n-A+1;i++){
    32             int maxn=0,minn=1e9;
    33             for(int k=i;k<=i+A-1;k++){
    34                 minn=min(minn,b[k][j]);
    35                 maxn=max(maxn,c[k][j]);
    36             }
    37             if(maxn-minn==ans) cnt++;
    38         }
    39     printf("%d %d",ans,cnt);
    40     return 0;
    41 }

    邻居(neighbor)

    【题目描述】

    你最近刚刚搬进翠湖旁的一条街道里居住,于是希望认识一下四周的邻居。你了解到,这条街上的住民共有n户,自西向东一字排列。

    你发现与其他街道不同的是,这条街上的所有住民被分为AB两组,两组轮流定期对翠湖的水质进行检测并上报。为了保证每次检测的准确性,环境部门规定这条街上的住户,对于任意的一段,在其中A组住户和B组住户的数目之差不超过p,而且A组住户和B组住户的数目都是确定的。你很关心你会被分到哪一组,所以你希望知道住户分组的方案数。

    【输入数据】

    输入只有一行,四个正整数n,A,B,p,分别表示住户总数、A组住户数、B组住户数和题干中所述常数p。

    【输出数据】

    输出只有一行,表示住户分组的方案数,答案对10^9+7取模

    【样例输入】

    5 2 3 1

    【样例输出】

    1

    【数据范围】

    对于20%的数据,A,B,p<=10;

    对于40%的数据,A,B<=50;

    另外20%的数据,p=1。

    对于100%的数据,1<=A,B<=150,1<=p<=20,n=A+B。

    【样例解释】

    只有一种分组方案BABAB。

  • 相关阅读:
    vue 循环Redio
    vue 子组件修改父组件变量问题
    docker安装redis
    vue 复制内容到粘贴板
    vue 组件传值
    vscode 打开多个标签页
    asp.net 文件分片上传
    css之图片下方定位遮掩层
    Python发送邮件脚本
    git添加秘钥提示Key is already in use
  • 原文地址:https://www.cnblogs.com/Beginner-/p/7656992.html
Copyright © 2020-2023  润新知