• 2017/9/13模拟赛


    粉饰(decorate)

    【题目描述】

    小D有一块被分为n*m个格子的矩形鱼片。为了装饰鱼片,小D决定给每个格子上色。由于小D很喜欢红白,所以小D给每个格子涂上了红色或白色,第i行第j列的格子颜色记为c[i,j]。涂完之后,小D想评估这块鱼片的“XY值”。我们定义一个有序无重复三元格子组{(x1,y1),(x2,y2),(x3,y3)}为“XY组”当且仅当:

    |(x1-x2)*(y1-y2)|+|(x3-x2)*(y3-y2)|=0

      (c[x1,y1]-c[x2,y2])*(c[x3,y3]-c[x2,y2])≠0

    一块鱼片的“XY值”为该块鱼片里“XY组”的数量。

    【输入数据】

    第一行两个正整数n,m。

    为描述整块鱼片,接下来n行,每行一个长度为m的01串,0表示白色,1表示红色。

    【输出数据】

    输出一行,一个整数表示这块鱼片的“XY值”。

    【样例输入】

    3 3

    011

    100

    011

    【样例输出】

        44

    【数据范围】

    本题采用子任务制。

    Subtask 1(20pts):1<=n,m<=100;

    Subtask 2(10pts):n=1;

    Subtask 3(20pts):n=3;

    Subtask 4~5(各25pts) 没有数据范围限制;

    对于100%的数据,1<=n*m<=4*10^6,0<=c[i][j]<=1。

    【样例解释】

        由于本题比较特殊,所以没有样例解释。

    题解:预处理行列的0,1个数,枚举x2即可。

    代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 int n,m;char x;
     6 long long ans,ans2,k;
     7 void add(){if(ans>=1e18) ans2++,ans-=1e18;}
     8 int main(){
     9     freopen("decorate.in","r",stdin);
    10     freopen("decorate.out","w",stdout);
    11     scanf("%d%d",&n,&m);
    12     int a[n+5][m+5],h0[n+5],h1[n+5],l0[m+5],l1[m+5];
    13     memset(h0,0,sizeof(h0));memset(h1,0,sizeof(h1));
    14     memset(l0,0,sizeof(l0));memset(l1,0,sizeof(l1));
    15     for(int i=1;i<=n;i++){
    16         scanf("%c",&x);
    17         for(int j=1;j<=m;j++){
    18             scanf("%c",&x);
    19             a[i][j]=x-'0';
    20             if(a[i][j]){h1[i]++;l1[j]++;}
    21             else{h0[i]++;l0[j]++;}
    22         }
    23     }
    24     for(int i=1;i<=n;i++)
    25         for(int j=1;j<=m;j++){
    26             if(a[i][j]) k=h0[i]+l0[j];
    27             else k=h1[i]+l1[j];
    28             ans+=k*(k-1); add();
    29         }
    30     if(ans2) printf("%lld%018lld",ans2,ans);
    31     else printf("%lld",ans);
    32     return 0;
    33 } 

    洞悉(insight)

    【题目描述】

    在走出了第6扇门后,小I终于可以使用他之前获得的水晶球了。当他透过水晶球看向前方,发现门的后面,是一扇又一扇无尽的门。n个房间排在一起,笔直地延伸向远方。为了让自己接下来的体验不算太差,小I想知道这n个房间中其中一些房间的信息,并进行一些修改。每个房间都有一个seed值。而小I有两种操作:

    1 x y:询问[x,y]区间的房间的seed值的乘积对1000000007的模;

    2 l r:将[l,r]区间里所有房间的seed值改为φ(seed)

    其中,φ(x)为欧拉函数,即小等于x的与x互质的数的个数

    【输入数据】

    第一行两个正整数n,m。

    第二行n个正整数,表示每个房间的seed值。

    接下来m行,每行表示一个小I的操作。

    【输出数据】

    对于每个操作1,输出一行询问的答案。

    【样例输入】

    5 6

    1 2 4 8 9

    1 1 2

    2 2 4

    2 1 3

    1 1 5

    1 2 3

    2 3 5

    【样例输出】

    32

    4

    24

    【数据范围】

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

    对于40%的数据,n,m<=50000;

    另外20%的数据,seed<=100000。

    对于100%的数据,1<=n,m<=200000,1<=seed<=10^7。

    【样例解释】

    下面给出每次操作得到的结果:

    ①序列变为1 1 4 8 9

        ②1*4*8=32

        ③1*1*4=4

        ④序列变为1 1 2 4 6

        ⑤序列变为1 1 1 4 6

        ⑥1*4*6=24

    题解:用线段树维护区间乘积和区间最大值,若区间最大值为1,则再取欧拉函数值也不会改变返回即可,可以证明,一个数取欧拉函数最多log(这个数)的步数,在这之前,我们预处理出范围内所有数的欧拉函数,用筛法实现。

    代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define Mod 1000000007
     5 #define MN 200005
     6 #define MS 10000005
     7 using namespace std;
     8 int n,m,phi[MS],pri[MS],cnt,a[MN];
     9 struct node{int pr,mx;}t[MN*3];
    10 void update(int k){
    11     t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
    12     t[k].pr=1LL*t[k<<1].pr*t[k<<1|1].pr%Mod;
    13 }
    14 void build(int k,int l,int r){
    15     if(l==r){t[k].mx=t[k].pr=a[l]; return;}
    16     int mid=l+r>>1;
    17     build(k<<1,l,mid); build(k<<1|1,mid+1,r);
    18     update(k);
    19 }
    20 int getpro(int k,int l,int r,int ql,int qr){
    21     if(ql==l&&qr==r) return t[k].pr;
    22     int mid=l+r>>1;
    23     if(qr<=mid) return getpro(k<<1,l,mid,ql,qr);
    24     else if(ql>mid) return getpro(k<<1|1,mid+1,r,ql,qr);
    25     else return 1LL*getpro(k<<1,l,mid,ql,mid)*getpro(k<<1|1,mid+1,r,mid+1,qr)%Mod;
    26 }
    27 void getdown(int k,int l,int r){
    28     if(t[k].mx==1) return;
    29     if(l==r){t[k].mx=t[k].pr=phi[t[k].mx]; return;}
    30     int mid=l+r>>1;
    31     getdown(k<<1,l,mid); getdown(k<<1|1,mid+1,r);
    32     update(k);
    33 }
    34 void getphi(int k,int l,int r,int ql,int qr){
    35     if(ql==l&&qr==r){getdown(k,l,r); return;}
    36     int mid=l+r>>1;
    37     if(qr<=mid) getphi(k<<1,l,mid,ql,qr);
    38     else if(ql>mid) getphi(k<<1|1,mid+1,r,ql,qr);
    39     else getphi(k<<1,l,mid,ql,mid),getphi(k<<1|1,mid+1,r,mid+1,qr);
    40     update(k);
    41 }
    42 int main()
    43 {
    44     phi[1]=1;
    45     for(int i=2;i<MS;i++){
    46         if(!phi[i]) pri[++cnt]=i,phi[i]=i-1;
    47         //i是个素数,i的fai=i-1 
    48         for(int j=1;i*pri[j]<MS;j++)
    49             if(i%pri[j]) phi[i*pri[j]]=phi[i]*phi[pri[j]];
    50             //如果a,b互质,则a*b的欧拉函数=a的欧拉函数*b的欧拉函数 
    51             else{phi[i*pri[j]]=phi[i]*pri[j]; break;}
    52             //如果b是素数,a是b的倍数,则a*b的fai=a的fai*b
    53     }
    54     scanf("%d%d",&n,&m);
    55     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    56     build(1,1,n);
    57     while(m--){
    58         int op,x,y;
    59         scanf("%d%d%d",&op,&x,&y);
    60         if(op==1) getphi(1,1,n,x,y);
    61         else printf("%d
    ",getpro(1,1,n,x,y));
    62     }
    63     return 0;
    64 }

     

    命令(order)

    【题目描述】

    小O开了许多年飞机,现在她准备更换自己的炮台。于是就有很多炮台来应聘。为了选拔最优秀的炮台,小O给炮台们下了一条指令,要求他们在n个数中,选出若干个数,使得它们两两之间的和不为质数,最后使得这些数的乘积尽可能大。作为一名优秀的炮台,为了使自己处于尴尬的境地,你需要又快又好地解决这个问题。

    【输入数据】

    第一行一个正整数n。

    第二行n个正整数a1~an,表示小O给出的数字。

    【输出数据】

    输出一行表示最大乘积,答案对10^9+7取模。

    【样例输入】

    6

    3 2 2 3 4 4

    【样例输出】

        64

    【数据范围】

    本题采用子任务制。

    Subtask 1(10pts):n<=13;

    Subtask 2(12pts):n<=23;

    Subtask 3(13pts):ai<=20;

    Subtask 4(15pts):ai<=2000;

    Subtask 5~6(各25pts):没有数据范围限制;

    对于100%的数据,1<=n<=1000,1<=ai<=5*10^5。

    【样例解释】

    选取2、2、4、4四个数,2*2*4*4=64。

     

  • 相关阅读:
    防止头文件的重复包含问题
    git常用命令
    redis
    linux常用操作
    数据库安装
    mysql修改表结构
    mysql 忘记root密码及授权访问
    mysql连表查询
    mysql 存取ip方法
    php批量修改表结构
  • 原文地址:https://www.cnblogs.com/Beginner-/p/7542559.html
Copyright © 2020-2023  润新知