【长沙集训】2017.9.22

今天的题,大概是比较考验打暴力的能力。

三道都是暴力,都是你认为你A了就WA成zz的。。

中午被ykk毒奶“你打暴力很稳啊”,然后就炸了。。。

 

T1 溢出

简单模拟,正经的Noip day1T1难度。一开始数据有误爆0,改后就A了。

读入,判断最大值除以当前值的商和读入值的关系。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long double LL;
using namespace std;
int ans,T,fl;
LL sum,tp,x,lim[20]={0,127,255,32767,65535,2147483647,4294967295,9223372036854775807,18446744073709551615};
char op[50];
inline LL read(int f) {
    LL res=0; char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) {res=res*10+ch-'0';}
    if(ch=='\n') fl=1;
    return res;
}
int main()
{
    //freopen("overflow.in","r",stdin);
    //freopen("overflow.out","w",stdout);
    scanf("%d",&T);
    while(T--) {
        int lz=0,ct=0,now;
        scanf("%s",&op);
        if(op[0]=='u') {lz=1;scanf("%s",&op);}
        if(!lz&&op[3]=='8') now=1;
        if(!lz&&op[3]=='1') now=3;
        if(!lz&&op[3]=='3') now=5;
        if(!lz&&op[3]=='6') now=7;
        if(lz&&op[3]=='8') now=2;
        if(lz&&op[3]=='1') now=4;
        if(lz&&op[3]=='3') now=6;
        if(lz&&op[3]=='6') now=8;
        sum=1; ans=0;
        for(int i=1;i;i++) {
            x=read(1);
            if(!ct) tp=lim[now]/sum;
            if(x>tp&&!ct) ans=i,ct=1;
            else sum*=x;
            if(fl==1) {
                if(!ct) cout<<"never"<<endl;
                else cout<<ans<<endl;
                fl=0;break;
            }
        }            
    }
    return 0;
}
View Code

 

 

 T2函数变换

暴力搜索。据说可以直接暴力求欧拉函数,求稳还是线筛预处理了10^7以内的。然后直接爆搜。

很不幸的预处理出来的东西单独开了个函数,然后那里面此次不按2操作做的直接返回了,忘了继续递归。。

然后三步运算符没有打括号。。。GG。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
const int maxn=1e7+299;
int ans,n,k,p[maxn],ol[maxn],bo[maxn],cs[maxn],T;
using namespace std;
void get_prime() {
    cs[1]=0;
    for(int i=2;i<=maxn-290;i++) {
        if(!bo[i]) {p[++p[0]]=i; ol[i]=i-1;}
        cs[i]=cs[ol[i]]+1;
        for(int j=1;j<=p[0]&&i*p[j]<=(maxn-290);j++) {
            bo[p[j]*i]=1;
            if(i%p[j]==0) { ol[i*p[j]]=ol[i]*p[j]; break; }
            else ol[p[j]*i]=ol[i]*(p[j]-1);
        }
    }
}
int fenjie(int n) {
    int tp=n,res=n;
    for(int i=2;i<sqrt(n);i++) if(tp%i==0) {
        res=res-res/i;
        while(tp%i==0) tp/=i;
        if(tp==1) break;
    }
        if(tp!=1) res=res/tp*(tp-1);
    return res;
}
int workx(int cnt,int kcs,int now) {
    if(now==1) return 0;
    if(kcs==k) return cs[now];
    else return min(workx(cnt+1,kcs+1,now/2+1)+1,workx(cnt,kcs,ol[now])+1);
}
int workd(int cnt,int kcs,int now) {
    int tp1=1e9,tp2=1e9;
    if(now==1) return 0;
    if(kcs==k) {
        if(now<=1e7) return cs[now]+1;
        int xx=fenjie(now);
        return xx>1e7?(workd(cnt+1,kcs,xx)+1):(cs[xx]+1);
    }
    tp1=(now/2+1>=1e7?(workd(cnt+1,kcs+1,now/2+1)+1):(workx(cnt+1,kcs+1,now/2+1))+1);
    if(now<=1e7) tp2=workx(cnt+1,kcs,cs[now])+1;
    else {
        int xx=fenjie(now);
        tp2=xx>=1e7?(workd(cnt+1,kcs,xx)+1):(workx(cnt+1,kcs,xx)+1);    
    }
    return min(tp1,tp2);
}
int main()
{
    //freopen("func.in","r",stdin);
    //freopen("func.out","w",stdout);
    scanf("%d",&T) ;
    get_prime();
    while(T--){
        scanf("%d%d",&n,&k);
        if(n<=1e7&&k==0) ans=cs[n];
        else if(n<=1e7) ans=workx(0,0,n);
        else ans=workd(0,0,n);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

 

T3跳跃切除子序列

枚举每个a的倍数,然后暴力匹配。写得比较玄,特判了从前往后直接配上和从后往前直接配上以及前后各一段匹配上的情况。

然后找到第一个不匹配的和第二个,他们的差作为公差的上限暴力匹配。

这题细节比较多,比较坑。。写的时候没有考虑两种情况:
1.可以配上但是应该删除。 这个很好改。

2.中间删除一段后后端直接匹配。可以问一下长度然后暴力匹配,但是发现数据比较水特判一下就过了,在下比较懒。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
const int maxn=1e5+299;
using namespace std;
int a[maxn],b[maxn],cc[maxn],T,s[maxn],aa,ss;
void jia(int a[],int b[],int c[]) {
    c[0]=max(a[0],b[0]);
    int tp=0;
    for(int i=1;i<=c[0];i++) {
        c[i]=(a[i]+b[i]+tp)%10;
        tp=(a[i]+b[i]+tp)/10;
    }
    while(tp) {
        c[++c[0]]=tp%10;
        tp/=10;
    }
    for(int i=0;i<=c[0];i++) a[i]=c[i];
}
int ok(int a[]) {
    int l=-1,r=-1,ll=0,rr=0,zp=0,yp=0;
    for(int i=s[0],j=a[0];i>=1;i--,j--) {
        if(a[j]!=s[i]) break;
        else zp++;
        if(i==1) return 1;
    }
    for(int i=1,j=1;i<=s[0];i++,j++) {
        if(a[j]!=s[i]) break;
        else yp++;
        if(i==s[0]) return 1;
    }
    if(zp+yp>=s[0]) return 1;
    for(int i=a[0],j=s[0];i>=1;i--) {
       if(a[i]!=s[j]||j==0)  {
           if(l==-1) l=i,ll=j;
           else if(r==-1) {r=i; rr=j; break;}
       }
       else j--;
    }
    for(int k=2;k<=l-r;k++) {
        for(int i=l-1,j=ll,pre=l;i>=1;i--) {
            if(a[i]!=s[j]||j==0) {
                if(i!=pre-k) break;
                pre=i;
            }
            else if(i==pre-k&&i!=1) pre=i;
            else if(j) j--;
            if(j==0&&i==1) return 1;
        }
    }
    return 0;
}
int main()
{
    //freopen("jumpcut.in","r",stdin);
    //freopen("jumpcut.out","w",stdout);
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&aa,&ss);
        if(ss%aa==0) {
            printf("%d\n",ss);
        }
        else {
            while(aa) {
                a[++a[0]]=aa%10;
                aa/=10;
            }
            for(int i=0;i<=a[0];i++) b[i]=a[i];
            while(ss) {
                s[++s[0]]=ss%10;
                ss/=10;
            }
            for(int i=1;i;i++) {
                if(a[0]<s[0]) ;  //TLE continue;
                else if(ok(a)) {
                    for(int j=a[0];j>=1;j--) printf("%d",a[j]);
                    printf("\n");
                    break;
                }
                jia(a,b,cc);
            }
            for(int i=a[0];i>=0;i--) b[i]=0;
            for(int i=a[0];i>=0;i--) a[i]=0;
            for(int i=s[0];i>=0;i--) s[i]=0;
            for(int i=cc[0];i>=0;i--) cc[i]=0;
        }
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Achenchen/p/7575534.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值