2017.9.14模拟考试

51 篇文章 0 订阅
45 篇文章 0 订阅

2017.9.14 模拟考试 解题报告

哈呀呀呀!Markdown吗!题目粘贴就这样子了。

P75
竞赛时间:????年??月??日??:??-??:??
题目名称
名称 hao jian dan
输入 hao.in jian.in dan.in
输出 hao.out jian.out dan.out
每个测试点时限 1秒 2秒 2秒
内存限制 512MB 512MB 512MB
测试点数目 20 20 20
每个测试点分值 5 5 5
是否有部分分 无 无 无
题目类型 传统 传统 传统
注意事项(请务必仔细阅读):
【问题描述】
从 中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数最大可能是多少。
【输入格式】
第一行一个数字 。
【输出格式】
一行一个整数代表答案对 取模之后的答案。
【样例输入】
7
【样例输出】
144
【样例解释】
但是塔外面有东西。
【数据规模与约定】
对于 的数据, 。
对于 的数据, 。
对于 的数据,。
对于 的数据,。

【问题描述】
有 个数,随机选择一段区间,如果这段区间的所有数的平均值在 中则你比较厉害。求你比较厉害的概率。
【输入格式】
第一行有三个数 ,含义如上描述。
接下来一行有 个数代表每一个数的值。
【输出格式】
输出一行一个分数 代表答案,其中 互质。如果答案为整数则直接输出该整数即可。
【样例输入1】
4 2 3
3 1 2 4
【样例输出1】
7/10
【样例输入2】
4 1 4
3 1 2 4
【样例输出2】
1
【样例解释】
塔外面有棵树。
【数据规模与约定】
对于 的数据,。
对于 的数据,。
对于 的数据, 。

【问题描述】
的方阵上有 棵葱,你要修一些栅栏把它们围起来。一个栅栏是一段沿着网格建造的封闭图形(即要围成一圈)。各个栅栏之间应该不相交、不重叠且互相不包含。如果你最多修 个栅栏,那么所有栅栏的长度之和最小是多少?
【输入格式】
第一行三个整数 。
接下来 行每行两个整数 代表某棵葱的位置。
【输出格式】
一行一个整数代表答案。
【样例输入1】
6 1 4
1 3
4 2
4 4
6 4
【样例输出1】
18
【样例输入2】
6 2 4
1 3
4 2
4 4
6 4
【样例输出2】
16
【样例解释】
你猜树上有啥。
【数据规模与约定】
对于 的数据, 。
对于 的数据, 。
对于 的数据, 。
对于 的数据, 。

三道题分别预计50+30+10=90 实测55+30+10=95
T1
质因数分解 反正找找规律不难发现 一个完全平方数乘以一个完全平方数一定还是一个完全平方数,好了那么久自认而然的想到质因数分解+快速幂。
首先筛出一些质数
求出每个质数用了几遍
计算答案,注意对于每一个素数只能去他的偶数次幂,既:假如质数3一共用了5次,那么他对答案的贡献只有3^4
有一点值得注意的是:50分做法和100分做法都是质因数分解+快速幂,100分做法在于能不能想到快速统计1-N的每个数字用了每个质数几遍
50统计方法:

inline void prepare(int x){
    int j=0;
    while(j<=5682&&x){
        while(x%prime[j]==0) x/=prime[j],++mp[prime[j]];
        ++j;
    }
}
for(i=2;i<=n;++i) prepare(i);

5682是我打表的素数,本来打了100W之内的,发现跑的太慢,有可能连50分都T,果断删掉
100分统计方法:

for(i=0;i<Num;++i){
int t=n;
    while(t){
        Sum[i]+=t/Prime[i];//这种计算每个质数用了几次的算法 很巧妙 
        t/=Prime[i];
    }
}

Num是我们求出的素数的个数,Sum[i]表示第i个素数用了几次
这样就能100分了
T2:
要求 区间平均值>=l&&<=r 的个数

现在我们来求区间平均值在1~r的个数和1~l(不包括l)的个数 前减后即为所求
以求1~r为例

(a[i]+a[i+1]+……+a[i+k-1])/k<=r 
(a[i]+a[i+1]+……+a[i+k-1])<=k*r 
(a[i]+a[i+1]+……+a[i+k-1])-k*r<=0 
(a[i]-r)+(a[i+1]-r)+……+(a[i+k-1]-r)<=0 

令c[i]=a[i]-r得到一个新数组c
即求c数组区间和<=0的个数
令s为数组c的前缀和数组
c[i]+c[i+1]+…+c[i+k-1]<=0
s[i+k-1]-s[i]<=0
s[i+k-1]<=s[i]

i< i+k-1
s[i]>=s[i+k-1]
即求s数组逆序对数
代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int MAXN = 500010;
LL n,l,r,ans1,ans2,a[MAXN],b1[MAXN],b2[MAXN],c[MAXN];
LL s1[MAXN],s2[MAXN];
#define lowbit(i) (i&(-i))
void Add(int x){
    for(int i=x;i<=n;i+=lowbit(i)) ++c[i];
}
LL Get_Sum(int x){
    LL ret=0;
    for(int i=x;i>=1;i-=lowbit(i)) ret+=c[i];
    return ret;
}
inline void read(LL &x){
    x=0; int f=1; char c=getchar();
    while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
    while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar();  } x*=f;
}
int main(){
    freopen("jian.in","r",stdin);
    freopen("jian.out","w",stdout);
    read(n),read(l),read(r);
    for(int i=1;i<=n;++i) read(a[i]);
    for(int i=1;i<=n;++i){
        s1[i]=s1[i-1]+a[i]-l;
        b1[i]=s1[i];
        if(s1[i]<0) ++ans1;
        s2[i]=s2[i-1]+a[i]-r;
        b2[i]=s2[i];
        if(s2[i]<=0) ++ans2;
    }
    sort(s1+1,s1+n+1);
    sort(s2+1,s2+n+1);
    LL t1=unique(s1+1,s1+n+1)-s1-1;
    LL t2=unique(s2+1,s2+n+1)-s2-1;
    for(int i=1;i<=n;++i){
        LL pos=lower_bound(s1+1,s1+1+t1,b1[i])-s1;
        b1[i]=pos;
        pos=lower_bound(s2+1,s2+1+t2,b2[i])-s2;
        b2[i]=pos;
    }
    for(int i=n;i>=1;--i){
        ans1+=Get_Sum(b1[i]);
        Add(b1[i]+1);
    }
    memset(c,0,sizeof c );
    for(int i=n;i>=1;--i){
        ans2+=Get_Sum(b2[i]);
        Add(b2[i]);
    }
    LL up=ans2-ans1;
    LL down = n*(n+1)/2;
    if(up % down == 0 ) cout<<up/down<<endl;
    else cout<<up/__gcd(up,down)<<'/'<<down/__gcd(up,down)<<endl;
    fclose(stdin);fclose(stdout);
    return 0;
}

T3
就是搜索
卡时也只能拿到95分,没啥好思路,有份题解没大看懂(那份能A)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<ctime>
#include<cstdlib>
using namespace std;
#define MAXN 25
#define INF 1000000000
int n,m,k,x[MAXN],y[MAXN],a[MAXN];
int mnx[MAXN],mny[MAXN],ans=INF,mxx[MAXN],mxy[MAXN];

void DFS(int t){
    if(clock()>=1950){ printf("%d\n",ans); exit(0); }
    if(t>n){
        int sum=0;
        for(int i=1;i<=k;++i)
            if(a[i]) sum+=(mxx[i]-mnx[i]+mxy[i]-mny[i]+2)*2;
        ans=min(ans,sum);
        return ;
    }
    int sum=0;
    for(int i=1;i<=k;++i)
        if(a[i]) sum+=(mxx[i]-mnx[i]+mxy[i]-mny[i]+2)*2;
    if(sum>=ans) return;
    for(int i=1;i<=k;++i){
        int pmnx=mnx[i],pmxx=mxx[i],pmny=mny[i],pmxy=mxy[i];
        mnx[i]=min(mnx[i],x[t]);mxx[i]=max(mxx[i],x[t]);
                mny[i]=min(mny[i],y[t]);mxy[i]=max(mxy[i],y[t]);
        ++a[i];
        DFS(t+1);
        mnx[i]=pmnx,mxx[i]=pmxx,mny[i]=pmny,mxy[i]=pmxy;
        --a[i];
    }
}

int main(){
    freopen("dan.in","r",stdin);
    freopen("dan.out","w",stdout);
    memset(mnx,127/3,sizeof mnx );
    memset(mny,127/3,sizeof mny );
    scanf("%d%d%d",&m,&k,&n);
    for(int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]);
    DFS(1);
    printf("%d\n",ans);
    fclose(stdin);fclose(stdout);
    return 0;
}

总结:
T1
大约一个小时多一点,想到了,质因数分解,但是没想到到校的统计策略,50分。。。
T2
前缀和+暴力,先打了出来,后来在想怎么优化,但是没想出来,大约就一个小时左右吧
T3
知道应该就是搜索,
两个相交的矩形,肯定不如合成一个矩形更优,但是就是没思路写代码,只写了k==1的情况。。。
总的来说:
时间安排还凑活,搜索没打好。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值