码迷,mamicode.com
首页 > 其他好文 > 详细

【考试记录】20181003

时间:2018-10-10 00:01:38      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:memset   ring   pac   end   相等   read   tin   algorithm   就是   

T1:

现在给你N+1个数,其中有N个数是合法的,合法的定义是A[i]=x*p[i],其中x为固定合数,p[i]为两两互异的质数。

还有一个数是不合法的,不合法即要么不满足除x的商是一个质数,要么不整除x,现在请找出那个不合法的数。

N<=10^5,x<=10^5,p[i]<=1.5*10^6。

 

题解:

如果所有合法的数都是形如一个大合数乘一个素数的,那我们直接从A[i]里随便取三个数两两求gcd,出现两次及以上的不就是x了?

既然这样,那我为什么一开始想了一堆log^2的奇形怪状的方法强行耽误时间……

(正北方的刘某同学写了表筛LLE(代码长度超限)了,堪称千古绝唱)

 

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;
#define MAXN 100005
#define MAXM 1500005
#define INF 0x7fffffff
#define ll long long

ll A[MAXN],p[MAXM],isp[MAXM],cnt;
inline ll read(){
    ll x=0,f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar())
        if(c==-)
            f=-1;
    for(;isdigit(c);c=getchar())
        x=x*10+c-0;
    return x*f;
}


inline void init(ll x){
    memset(isp,-1,sizeof(isp));
    for(ll i=2;i<=x;i++){
        //cout<<i<<endl;
        if(isp[i]==-1) p[++cnt]=i,isp[i]=1;
        for(ll j=1;j<=cnt;j++){
            if(i*p[j]>x) break;
            isp[i*p[j]]=0;
            if(i%p[j]==0) break;
        }
    }
    return;    
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    init(MAXM-5);
    ll N=read(),num=0,maxm=0,x=-1;
    bool flag=0;
    for(ll i=1;i<=N+1;i++) A[i]=read();
    for(ll k=1;k<=MAXN;k++){
        bool tp1=0;ll tp2=0;
        for(ll i=1;i<=N+1;i++){
            if(A[i]/k>MAXM-5) {if(tp1) break;else tp1=1;}  
            else if(!isp[A[i]/k] || A[i]==k || A[i]%k!=0) {if(tp1) break;else tp1=1;}  
            else tp2++;if(tp2==3) {x=k;flag=1;break;}
        }
        if(flag) break;
    }
    for(ll i=1;i<=N+1;i++)
        if(A[i]/x>MAXM-5 || !isp[A[i]/x] || A[i]%x!=0)
            {printf("%lld\n",A[i]);break;}
    return 0;
}

 

 

T2:

给你N块密度均匀且宽,高相等的积木坐标li,ri,现在需要你把这N块积木按序分成任意座积木塔,

你需要保证把所有积木塔从低到高搭起来时不会出现不稳定结构,问含积木块数最多的积木塔最少可以含多少块积木。

稳定的定义:

若一个积木塔有N层,当且仅当对于任意i属于[1,N),从上至下数,前i块积木的重心落在第i+1块积木的覆盖范围内,
则稳定,否则不稳定。前i块积木的重心为前i块积木的几何中心,以质量为权重的带权平均位置。

N<=10^3,li,ri<=10^4。

 

题解:

这题最难的点在于知道带权平均数是形如ave=Σxi*wi/Σwi的表达式。

然后就没难点了……设dp[i]表示从下到上处理到第i块积木的答案,

预处理i-j是否稳定后枚举最后一座塔的形态即可实现O(N^2)转移。

 

代码:(手懒贴了wls巨佬的)

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
inline ll read() {
    ll x=0,f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch==-) f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-0;
    return x*f;
    
}
int n;
double L[1005],R[1005];
double g[1005][1005],sz[1005][1005];
bool vis[1005][1005];
int dp[1005];
int main() {
    n=read();
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) vis[i][j]=1;
    for(int i=1;i<=n;i++) {
        scanf("%lf%lf",&L[i],&R[i]);
        g[i][i]=(R[i]+L[i])/2;sz[i][i]=(R[i]-L[i]);
        vis[i][i]=1;
    }
    for(int i=1;i<=n;i++) {
        for(int j=i+1;j<=n;j++) {
            sz[i][j]=sz[i][j-1]+R[j]-L[j];
            g[i][j]=(g[i][j-1]*sz[i][j-1]+g[j][j]*sz[j][j])/sz[i][j];
            vis[i][j]=vis[i][j-1];
            if(!(g[i][j-1]>=L[j]&&g[i][j-1]<=R[j])) vis[i][j]=0;
        }
    }
    memset(dp,27,sizeof(dp));
    dp[n+1]=0;
    for(int i=n;i>=1;i--) {
        for(int j=i;j<=n;j++) {
            if(!vis[i][j]) break;
            if(!vis[i][n]) continue;
            if(j==n||(g[i][j]>=L[j+1]&&g[i][j]<=R[j+1])) dp[i]=min(dp[i],max(dp[j+1],j-i+1));
        }
    }
    printf("%d\n",dp[1]);
}

 

T3:

两列火车第一列na节车厢,第二列nb节车厢,每个车厢里有若干个1-N之间的整数,每个整数在两列车里出现且仅出现一次。

现在你需要按某种顺序排列车厢,然后把第一列车的车厢中的数按顺序取出扔到栈1,第二列扔到栈2。

再对栈1栈2进行k次操作,每次操作弹出一个栈顶放到另一个栈顶。k次操作后1-N每个数都要在栈1顶出现过一次。

问如何排列车厢使得k最小。

N<=10^5,na,nb<=20。

 

题解:

看了lv神的题解还是只会写暴力啊……

暴力枚举车厢的排列顺序然后计算每种排列顺序的答案(这句话极其难以实现)后取min。

正解大概是预处理出同一列车内车厢间连线数,车厢内连线距离,车厢到对侧列车连线数后状压DP。

 

代码:(同上std)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define MAXN 100010
#define MAXH 20
using namespace std;
const int Size=1<<16;
char buffer[Size],*head,*tail;
inline char Getchar() {
    if(head==tail) {
        int l=fread(buffer,1,Size,stdin);
        tail=(head=buffer)+l;
    }
    if(head==tail) return -1;
    return *head++;
}
inline int read()
{
    int x=0,t=1,c;
    while(!isdigit(c=Getchar()))if(c==-)t=-1;
    while(isdigit(c))x=x*10+c-0,c=Getchar();
    return x*t;
}
int N,n[2];
int k[2][MAXH],s[2];
int side[MAXN],block[MAXN],pos[MAXN];
long long opposite[2][MAXH];
long long link[2][MAXH][MAXH];
long long inside[2][MAXH];
long long cross[2][MAXH][MAXH];
long long f[2][1<<MAXH];
long long cf[2][1<<MAXH];
long long csum[2][MAXN];
long long lsum[MAXH][1<<MAXH];
int LOG[1<<MAXH];
int base;
int rev(int x){return (~x)&base;}
int lowbit(int x){return x&-x;}
void GetLinkSum(int side,int j,int x)
{
    int revx=rev(x),key=lowbit(revx),from=revx-key;
    lsum[j][x]=lsum[j][rev(from)]+link[side][j][LOG[key]];
}
long long TakeMin(long long &a,long long b)
{
    return a=min(a,b);
}
void Update(int side,int state)
{
    long long Remain=0;
    for(int i=0;i<n[side];i++)
    {
        bool hasi=state&(1<<i);
        if(!hasi)Remain+=k[side][i];
    }
    for(int i=0;i<n[side];i++)
    {
        int newstate=state|(1<<i);
        long long Raise=0,Cro;
        if(!(state&(1<<i)))
        {
            Raise=inside[side][i]+opposite[side][i]*(Remain-k[side][i]);
            Raise+=lsum[i][newstate];
            Cro=(cf[side][state]+cf[side][newstate]-csum[side][i])/2;
            Raise+=Cro*k[side][i];
            TakeMin(f[side][newstate],f[side][state]+Raise);
        }
    }
}
void BuildTransdata(int side,int x)
{
    int key=lowbit(x),from_state=x-key;
    long long ret=cf[side][from_state];
    for(int i=0;i<n[side];i++)
    {
        if((1<<i)&key)
        {
            key=i;
            break;
        }
    }
    for(int i=0;i<n[side];i++)
    {
        if(i==key)continue;
        if((1<<i)&x)
        {
            ret-=cross[side][i][key];
        }
        else
        {
            ret+=cross[side][i][key];
        }
    }
    cf[side][x]=ret;
}
int main()
{
    N=read();n[0]=read();n[1]=read();
    for(int i=0;i<n[0];i++)
    {
        k[0][i]=read();
        s[0]+=k[0][i];
        for(int j=1;j<=k[0][i];j++)
        {
            int node=read();
            side[node]=0;
            block[node]=i;
            pos[node]=j;
        }
    }
    for(int i=0;i<n[1];i++)
    {
        k[1][i]=read();
        s[1]+=k[1][i];
        for(int j=1;j<=k[1][i];j++)
        {
            int node=read();
            side[node]=1;
            block[node]=i;
            pos[node]=j;
        }
    }
    opposite[side[1]][block[1]]++;
    inside[side[1]][block[1]]+=k[side[1]][block[1]]-pos[1]+side[1];
    for(int x=1;x<N;x++)
    {
        int y=x+1;
        if(side[x]!=side[y])
        {
            opposite[side[x]][block[x]]++;
            opposite[side[y]][block[y]]++;
            inside[side[x]][block[x]]+=k[side[x]][block[x]]-pos[x]+side[x];
            inside[side[y]][block[y]]+=k[side[y]][block[y]]-pos[y]+side[y];
        }
        else
        {
            if(block[x]==block[y])
            {
                inside[side[x]][block[x]]+=abs(pos[x]-pos[y]);
            }
            else
            {
                cross[side[x]][block[x]][block[y]]++;
                cross[side[x]][block[y]][block[x]]++;
                link[side[x]][block[x]][block[y]]+=k[side[x]][block[x]]-pos[x]+pos[y];
                link[side[x]][block[y]][block[x]]+=k[side[x]][block[y]]-pos[y]+pos[x];
            }
        }
    }
    cf[0][0]=0;
    cf[1][0]=0;
    for(int i=1;i<(1<<n[0]);i++)BuildTransdata(0,i);
    for(int i=1;i<(1<<n[1]);i++)BuildTransdata(1,i);
    for(int i=0;i<n[0];i++)
        for(int j=0;j<n[0];j++)
            csum[0][i]+=cross[0][i][j];
    for(int i=0;i<n[1];i++)
        for(int j=0;j<n[1];j++)
            csum[1][i]+=cross[1][i][j];
    memset(f,127,sizeof f);
    f[0][0]=f[1][0]=0;
    for(int i=2;i<(1<<n[0]);i++)LOG[i]=LOG[i>>1]+1;
    base=(1<<n[0])-1;
    for(int i=0;i<n[0];i++)lsum[i][base]=0;
    for(int i=0;i<n[0];i++)
        for(int j=base-1;j>=0;j--)
            GetLinkSum(0,i,j);
    for(int i=0;i<(1<<n[0])-1;i++)
        Update(0,i);
    for(int i=2;i<(1<<n[1]);i++)LOG[i]=LOG[i>>1]+1;
    base=(1<<n[1])-1;
    for(int i=0;i<n[1];i++)lsum[i][base]=0;
    for(int i=0;i<n[1];i++)
        for(int j=base-1;j>=0;j--)
            GetLinkSum(1,i,j);
    for(int i=0;i<(1<<n[1])-1;i++)
        Update(1,i);
    printf("%lld\n",f[0][(1<<n[0])-1]+f[1][(1<<n[1])-1]);
}

 

【考试记录】20181003

标签:memset   ring   pac   end   相等   read   tin   algorithm   就是   

原文地址:https://www.cnblogs.com/YSFAC/p/9757076.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!