2017/10/30模拟赛总结

来源:2016day2
分数:70+65+100
估分:100+65+100

T1

反思

其实写了质因子分解而且写了好久。不过事实上写的是对的但是。把所有的2000都打成1000导致运行错误少了30。

T2

题意

有n条蚯蚓。每次都会把最长的一条切成两部分,比例为v:(u-v),前者向下取整,后者为原长减前者。除了被切的那一条,剩下所有的蚯蚓长度都会增加q。如果有蚯蚓长度一样,那么随便选择一条切。
现在这个人要切m次蚯蚓。求t,2t,3t…m-m%t次切的蚯蚓原长度是多少。
以及切完m次后剩下蚯蚓长度排t,2t,3t…(n+m)-(n+m)%t的长度是多少。

分析

一开始弄了个优先队列瞎搞不过复杂度一算就不对。不过还是水到65了。不过那边手写堆的似乎到了95…= =

首先其实可以发现蚯蚓肯定是从大到小切的。切出来的蚯蚓按比例分开的话,也是总大到小满足单调递减的。
一开始想着怎么快速的把新切出来的东西放进去的我还是too simple.这里首先先把原来的蚯蚓排一个序,然后开始切。每次切成两半都会满足单调递减,但是两半放在一起排来排去还是很麻烦。所以干脆的把他们存在两个队列里。
那么就是先给所有的蚯蚓排序,放在第一个队列里,然后每切掉一条蚯蚓,就把它分成两部分,放在第二和第三个队列里即可。

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define pb push_back
#define N 100005
#define M 7000005
#define inf 1000000007
using namespace std;

void read(int &x){
    x=0; char c=getchar();
    for (; c<'0'; c=getchar());
    for (; c>='0'; c=getchar())x=(x<<3)+(x<<1)+(c^'0');
}
bool cmp(int x,int y){return x>y;}
int q1[N],q2[M],q3[M];
const int o=0;
int main(){
    int n,m,q,u,v,t,i;
    read(n); read(m); read(q); read(u); read(v); read(t);
    for (i=0; i<N; i++)q1[i]=-inf;
    for (i=1; i<=n; i++)read(q1[i]);
    sort(q1+1,q1+n+1,cmp);
    for (i=0; i<M; i++)q2[i]=q3[i]=-inf;
    int l1=1,l2=1,l3=1,r2=0,r3=0,now=0;
    for (i=1; i<=m; i++){
        int res=-inf;
        if (res<q1[l1])res=q1[l1];
        if (res<q2[l2])res=q2[l2];
        if (res<q3[l3])res=q3[l3];
    //  printf("res=%d\n",res);
        if (i%t==0)printf("%d ",res+now);
        int l=(1ll*res+now)*1ll*u/v,r=res+now-l;
        now+=q;
        q2[++r2]=l-now; q3[++r3]=r-now;
        if (res==q1[l1])l1++;
        else if (res==q2[l2])l2++;
        else l3++;
    }
    printf("\n");
    for (i=1; ; i++){
        int res=-inf;
        if (res<q1[l1])res=q1[l1];
        if (res<q2[l2])res=q2[l2];
        if (res<q3[l3])res=q3[l3];
        if (res==-inf)return (o-o);
        if (i%t==0)printf("%d ",res+now);
        if (res==q1[l1])l1++;
        else if (res==q2[l2])l2++;
        else l3++;
    }   
    printf("\n");
    return 0;
}

T3

分析

其实就只是一个简单的状压DP。
我采用了先用 n3 求所有抛物线能炸到的猪。因为原点已经确定,然后再确定两个点就可以确定一条抛物线了。然后再来一下确认这条抛物线能炸到哪些猪。保存状态。
2n 的来枚举一下所有的状态向后转移就好了。
其实明明作为第三题却比第二题简单...你和day1是串通好的吗

#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
#define pb push_back
#define eps (1e-9)
using namespace std;

void read(int &x){
    x=0; char c=getchar();
    for (; c<'0'; c=getchar());
    for (; c>='0'; c=getchar())x=(x<<3)+(x<<1)+(c^'0');
}


const int o=0;
int dp[1<<19],q[19*19];
bool vis[1<<19],can[20];
double x[20],y[20];
inline void Min(int &x,int y){if (x>y)x=y;}

struct AC{double x,y;}A[20];
bool cmp(AC a,AC b){return a.x<b.x;}

int main(){
//  freopen("angrybirds.in","r",stdin);
//  freopen("angrybirds.out","w",stdout);
    int t,n,m,i,j,k,h,s,tmp,num;
    double a,b;
    read(t);
    for (; t; t--){
        memset(dp,63,sizeof(dp)); memset(can,0,sizeof(can));
        read(n); read(m); h=0;
        for (i=0; i<n; i++)scanf("%lf%lf",&A[i].x,&A[i].y);
        sort(A,A+n,cmp);
        for (i=0; i<n; i++)x[i]=A[i].x,y[i]=A[i].y;
        for (i=0; i<n; i++){
            for (j=i+1; j<n; j++)if (fabs(x[i]-x[j])>eps){
                if (x[i]*y[j]-x[j]*y[i]>-eps)continue;
                a=(y[i]*x[j]-y[j]*x[i])/(x[i]*x[j]*(x[i]-x[j]));
                b=(y[i]-a*x[i]*x[i])/x[i];
    //          printf("a=%.5f b=%.5f\n",a,b);
                s=0;
                for (k=0; k<n; k++)if (fabs(a*x[k]*x[k]+b*x[k]-y[k])<eps)can[k]=1,s|=1<<k;
                if (!vis[s])vis[s]=1,q[h++]=s;
    //          printf("s=%d\n",s);     
            }
            if (!can[i]){vis[1<<i]=1,q[h++]=1<<i;}
        }
        tmp=1<<n;  dp[0]=0;
        for (i=0; i<tmp; i++){
            num=dp[i]+1;
            for (j=0; j<h; j++)Min(dp[i|q[j]],num);
        }
        printf("%d\n",dp[tmp-1]);
        for (i=0; i<h; i++)vis[q[i]]=0;  
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值