校内模拟赛(20170921)

救命啊,救命啊!学长出丧题啦!!!

学长他们压榨我们的劳动力,然后带着我们的成绩跑了,无奈的我们只好玩命的调程序,把学长留给我们的丧题做完(划掉)

65分的rank 1跑路。

————————————————我是分割线————————————————

T1:粉饰(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。

【样例解释】

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

————————————————我是分割线————————————————

T1:sb题

显然我们就只有两种情况:1、3个点都在同一排,2、三个点呈L形,然后我们前缀和统计每行每列0和1总和,枚举中间点,预处理组合数C(n,2),直接暴力出答案就好了。

但是!学长!他出了爆long long的数据啊!又是爆long long这种坑点。。上次已经被学长坑过一次了。。(Cry~~~~~)

那么对于这种情况的处理方法,我们用两个long long压答案就好了,因为每次加上的数都不会超过long long....

#include<cstdio>
#define MN 4000005
using namespace std;
int h[MN][2],r[MN][2],a[MN];
long long qaq[MN];
int n,m;
long long ans1,ans2;
void add(long long q){ans1+=q,ans2=ans1>=1e18?ans2+1:ans2,ans1=ans1>=1e18?ans1-1e18:ans1;}
int main(){
    freopen("decorate.in","r",stdin);
    freopen("decorate.out","w",stdout);
    scanf("%d%d",&n,&m);
    int x;char ch;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
        ch=getchar();
        while(ch!=‘0‘&&ch!=‘1‘)ch=getchar();
        a[(i-1)*m+j]=ch-‘0‘;
    }
    qaq[1]=qaq[0]=0;qaq[2]=1;
    for(int i=3;i<=4000000;i++)qaq[i]=qaq[i-1]+i-1;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)x=a[(i-1)*m+j],h[i][x]++,r[j][x]++;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)add((qaq[h[i][a[(i-1)*m+j]^1]]+qaq[r[j][a[(i-1)*m+j]^1]]+h[i][a[(i-1)*m+j]^1]*r[j][a[(i-1)*m+j]^1])*2);
    if(ans2)printf("%lld%018lld\n",ans2,ans1);
    else printf("%lld\n",ans1);
    fclose(stdin);
    fclose(stdout);
}

————————————————我是分割线————————————————

T2:洞悉(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

————————————————我是分割线————————————————

这道题目明显的线段树,但是有一个问题,那就是我们做不到区间修改,因为一个区间的乘积取完欧拉函数值后和区间内的数每一个取欧拉函数值后的乘积没有任何关系。

所以我们只能单点修改,很快我们发现一个性质,那就是我们一个点最多只能修改24次(至于为什么可以自己拿个暴力跑一下),所以我们记一下区间的修改次数,如果>24就不修改了。

相当简单的QAQ,但是我忘记加#include<cstdio>导致编译错误了(这种错误绝不能再犯了。。。这是我的锅,怒丢了100分)

下面贴代码:

#include<iostream>
#include<cstdio>
#include<string>
#define MN 200005
#include<cstring>
using namespace std;
const int MAXN=10000005;
const int mod=1000000007;
bool vis[MAXN];
int phi[MAXN],a[MN],prime[MAXN],n,m,opt,x,y;
struct tr{
    long long num;
    int tt;
}t[MN<<2];
void Prime(int n)
{
    int cnt=0;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<n;i++)
    {
        if(!vis[i])
        {
            prime[cnt++]=i;
            phi[i]=i-1;
        }
        for(int j=0;j<cnt&&i*prime[j]<n;j++)
        {
            __int64 k=i*prime[j];
            vis[k]=1;
            if(i%prime[j]==0)
            {
                phi[k]=phi[i]*prime[j];
                break;
            }
            else
            phi[k]=phi[i]*(prime[j]-1);

        }
    }
}
void build(int l,int r,int k){
    if(l==r){t[k].num=a[l];return;}
    int mid=l+r>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    t[k].num=t[k<<1].num*t[k<<1|1].num%mod;
}
void update(int l,int r,int a,int b,int k){
    if(a<=l&&r<=b){
        t[k].tt++;
        if(l==r){
            t[k].num=phi[t[k].num];
            return;
        }
    }
    int mid=l+r>>1;
    if(a<=mid&&t[k].tt<21)update(l,mid,a,b,k<<1);
    if(b>mid&&t[k].tt<21)update(mid+1,r,a,b,k<<1|1);
    t[k].num=t[k<<1].num*t[k<<1|1].num%mod;
}
long long query(int l,int r,int a,int b,int k){
    if(l==a&&r==b)return t[k].num;
    int mid=l+r>>1;
    if(b<=mid)return query(l,mid,a,b,k<<1);
    if(a>mid) return query(mid+1,r,a,b,k<<1|1);
    return (query(l,mid,a,mid,k<<1)*query(mid+1,r,mid+1,b,k<<1|1))%mod;
}
int main()
{
    freopen("insight.in","r",stdin);
    freopen("insight.out","w",stdout);
    Prime(10000001);phi[1]=1;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    build(1,n,1);
    while(m--){
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1)update(1,n,x,y,1);
        else printf("%lld\n",query(1,n,x,y,1));
    }
    fclose(stdin);
    fclose(stdout);
}

————————————————我是分割线————————————————

命令(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。

————————————————我是分割线————————————————

本次考试最丧的一题。

首先我们考虑一个性质:对于除2以外的数,素数都是奇数。

又由于我们取1是没有必要的(除非只有一个1,但是这也不影响答案,下面会讲);

所以我们根据上面的性质,我们把数分为2部分,奇数和偶数。(保证两边自己内部不会产生奇数)

然后我们对于两个相加是素数的点,相互连inf的边;跑一个最小割就好了

但是由于我们这题是乘积最大!所以我们要化乘为加,方法是对每条边取log

还有个问题,我们不能直接根据答案得出方案。所以我们还需要。。。根据网络流的特性判断方案。

从S开始bfs,对于左半边的点,如果我们发现可以遍历到,就表示需要纳入答案,对于右半边的点,如果我们发现不能遍历到,那么就需要纳入答案(至于为什么,考虑一下最小割的性质,在这里我就不讲了。)

然后就解决啦!!手都断了。。

考后自己打了一边,竟然一遍过,感觉自己萌萌哒~,看来集训还是有效的

下面贴代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#define min(a,b) ((a)<(b)?(a):(b))
#define eps 1e-8
#define mod 1000000007
#define MN 1005
using namespace std;
double aabs(double aa){return aa>0?aa:-aa;}
int head[MN],iter[MN],level[MN],que[MN],a[MN],b[2][MN],n,tt1,tt2,num=1,S,T;
struct edge {
    int to,next;
    double w;
}g[MN*MN<<1];
bool pri[MN*MN],u[MN],vis[MN];
void bfs(){
    int h=1,t=1;vis[S]=u[S]=1;que[1]=S;
    while(h<=t){
        int tmp=que[h++];
        for(int i=head[tmp];i;i=g[i].next)if(!vis[g[i].to]&&g[i].w>eps)u[g[i].to]=vis[g[i].to]=1,que[++t]=g[i].to;
    }
}
bool spfa(){
    memset(level,0,sizeof(level));
    memcpy(iter,head,sizeof(head));
    int h=1,t=1;level[S]=1;que[1]=S;
    while(h<=t){
        int tmp=que[h++];
        for(int i=head[tmp];i;i=g[i].next)if(!level[g[i].to]&&g[i].w>eps)level[g[i].to]=level[tmp]+1,que[++t]=g[i].to;
    }return level[T]!=0;
}
double dfs(int u,double flow){
    if(u==T)return flow;
    double used=0;
    for(int &i=iter[u];i;i=g[i].next)
        if(level[g[i].to]==level[u]+1&&g[i].w>eps){
            double qaq=dfs(g[i].to,min(g[i].w,flow-used));
            g[i].w-=qaq,g[i^1].w+=qaq,used+=qaq;
            if(aabs(used-flow)<eps)return flow;
        }
    return used;
}
void dinic(){
    double now;
    while(spfa())do now=dfs(S,1e9);while(now>eps);
}
void ins(int u,int v,double w){g[++num].next=head[u];head[u]=num;g[num].to=v;g[num].w=w;}
void insw(int u,int v,double w){ins(u,v,w);ins(v,u,0);}
int main(){
    freopen("order.in","r",stdin);
    freopen("order.out","w",stdout);
    for(int i=2;i<=1000000;i++)for(int j=i+i;j<=1000000;j+=i)pri[j]=true;pri[1]=true;
    scanf("%d",&n);S=0,T=n+1;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[a[i]%2][a[i]%2?++tt2:++tt1]=a[i];
    for(int i=1;i<=tt1;i++)for(int j=1;j<=tt2;j++)if(!pri[b[0][i]+b[1][j]])insw(i,j+tt1,1e9);
    for(int i=1;i<=tt1;i++)insw(S,i,log2(b[0][i]));
    for(int i=1;i<=tt2;i++)insw(i+tt1,T,log2(b[1][i]));
    dinic(),bfs();
    long long ans=0;
    for(int i=1;i<=tt1;i++)if(u[i])ans=ans==0?b[0][i]:(ans*b[0][i])%mod;
    for(int i=1;i<=tt2;i++)if(!u[i+tt1])ans=ans==0?b[1][i]:(ans*b[1][i])%mod;
    printf("%lld\n",ans);
    fclose(stdin);
    fclose(stdout);
}
时间: 2024-10-10 20:26:19

校内模拟赛(20170921)的相关文章

2017.6.11 校内模拟赛

题面及数据及std(有本人的也有原来的) :2017.6.11 校内模拟赛 T1 自己在纸上模拟一下后就会发现 可以用栈来搞一搞事情 受了上次zsq 讲的双栈排序的启发.. 具体就是将原盘子大小copy一下排个序 用两个指针维护两个数组(原数据 和 排序后的数据), 即分为1数据和2数组 将小于1指针指向的数据的2数组中的数据全部压入栈中 后进行消除, 将栈栈顶元素与当前1数组中的1指针指向的元素进行比较 相同则消除 后重复过程 直至指针超过N 后判断一下是否两个指针都超过了N... #incl

校内模拟赛 Zbq&#39;s Music Challenge

Zbq's Music Challenge 题意: 一个长度为n的序列,每个位置可能是1或者0,1的概率是$p_i$.对于一个序列$S$,它的得分是 $$BasicScore=A\times \sum_{i=1}^{n}{S_i} \tag{1}$$ $$ combo(i)=\left\{ \begin{aligned} &S_i & &i=1 \\ &combo(i-1)+1 & &i\neq 1 ~\mathrm{and}~ S_i=1 \\ &

[20180816]校内模拟赛

T1 清理(clear) 问题描述 小 C 最近自己开发了一款云盘软件,目前已有??个用户.小C 的云盘上的文件会被后台分成两种类型,活动 文件和非活动文件,活动文件即可能常用的文件,会被放在高速服务器上给用户提供高速下载服务.用户 上传一个文件时,这个文件会被设置为活动文件.由于高速服务器内存大小有限,小 C 需要把一些文件 设为非活动文件,有以下两种设置方式:1.把上传时间前??早的文件全部设为非活动文件:2.把第??个用户上 传的文件全部设为非活动文件.注意这两种方式操作的对象都是所有文件

校内模拟赛T1大美江湖

这就是一个模拟题,注意1234分别对应左右上下横坐标和纵坐标的判断就好了 题解: 需要注意的是,向上取整ceil函数是对于一个double值返回一个double值,也就是说在ceil里面的类型一定要是double,否则会炸 代码: #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> #include<cstring> #include<string>

校内模拟赛:确定小组

  [问题描述] 有n个人坐成一排,这n个人都在某一个小组中,同一个小组的所有人所坐的位置一定是连续的. 有一个记者在现场进行采访,他每次采访都会询问一个人其所在的小组有多少人,被询问的每个人都给出了正确的答案,但是由于时间仓促,记者不一定询问了每个人,我们记录一个长度为n的答案序列,序列的第i个数表示第i个人的回答,如果为0则表示记者没有询问过这个人. 记者发现,对于一些情况,他可以唯一确定这排所有人的分组,而对于另外一些情况则不能,于是记者开始好奇,对于某一个答案序列,他能不能做到这一点,如

校内模拟赛20170604

香蕉锤--双向链表 #include<iostream> #include<cstdio> using namespace std; inline int read(){ int num=0,t=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();} ret

5.13 校内模拟赛

... 果然是dalao们做难题做多了后 简单题水不起来了吗.. 5.13解题报告 300分 T1写了差不多30~40分钟 T2写了不到5min (当时怀疑有坑..) T3推了大概1个多小时的式子, 然后又加上调试差不多一个半小时 时间分配就这样..感觉T2出的太过简单了..直接是个模板 T1 并查集 + 乱搞 T2 快速幂模板 T3 Dp T1 : codevs 2796 最小完全图 二次联通门 : codevs 2796 最小完全图 /* codevs 2796 最小完全图 并查集 + 乱搞

校内模拟赛(20170924)

四校很丧,但是学长的题目更简单 lrb学长的题目为什么都要倒着切,不懂QAQ ----------------我是分割线---------------- T1:个人卫生综合征 每天BBS都要从家里经过城市中的一段路到学校刷五三.城市中一共有n个路口和m条双向道路,每条双向道路都连接着两个路口ai.bi且有一定的时间花费vi.BBS家编号为1,学校编号为n.今天,BBS由于个人卫生综合征导致他很迟才离开家,他想用膜法改变k条道路的长度使通过其的时间花费vi变为0.现在他问你改变道路长度之后他到学校

校内模拟赛(20170917)

这套题目也是比较恶心的,....都是奇技淫巧的说. ----------------我是分割线------------------ T1:消消乐(tet) [题目描述] 有一个2n个数字排成一列,这个数列中由1..n中的数字组成,每个数字都恰好出现两次.每个回合可以交换相邻两个数字,交换以后如果有两个相同的数字相邻,那么将这两个数字消除,并将这两个数字的两端拼起来:如果拼接后的数列仍有相同的数字相邻,那么将引发连锁反应直到没有两个相同数字相邻.现在你想知道最少需要几个回合可以消除所有的数字. [