考前XJB打暴力系列

来源:互联网 发布:c语言教材 kindle 编辑:程序博客网 时间:2024/05/14 13:57

【NOI之前】
作为一个弱省的D类宝宝…NOI这种东西全凭运气!因为没有实力!所以我们不以A题为目标,而要以骗分为目标!

然后做了一点前些年NOI的题…不过都是非正解,但是考场上拿到比较高的暴力分也是很不错了…


【NOI 2016 国王饮水记】

分析:出题人给了将近10个性质才把这题给A了…

正解是斜率优化DP+巨大脑洞,但是我看过去这不就是贪心吗哈哈哈哈。

首先观察到性质1:水量小于一号点水量的没有卵用。下文默认没有这些小的水量。

然后手玩一会发现规律:当k足够大时,可以把>1号点水量的水从小到大排序,逐一和1号点取平均数。

那么k不够大的时候怎么办,假设排序后的水总共有cnt个(代码中从大到小排序),那么把编号为k~cnt的水逐一试着一起取,找个最大值作为当前答案。之后再在1~k-1中一个一个取。

然后一测大样例,maya竟然误差这么小,于是我天真的以为是精度问题就自信交给OJ了。

最后可以get 61 pts,后面的大样例莫名其妙部分正确很令我感动。

正解果然很难,我作为一个小蒟蒻才不会想呢。(关键是想不到)

代码贴出来主函数部分。

// ---------- decimal lib end ----------Decimal h[mxn];Decimal inv;int main() {//  Decimal test=1.0;//  test=test/3;//  std::cout<<test.to_string(50)<<"\n";    scanf("%d%d%d",&n,&k,&p);    fo(i,1,n) scanf("%d",&x[i]);    Decimal now=x[1];    sort(x+1,x+n+1);    for(int i=n;i>=1;i--)    {        if(x[i]>now) h[++cnt]=x[i];        else break;    }    if(cnt>k)    {        Decimal tmp=now;        fo(i,k,cnt)        {            tmp=tmp+h[i];            if(tmp/(i-k+2)>now)              now=tmp/(i-k+2);        }        cnt=k-1;    }    for(int i=cnt;i>=1;i--)    {        now=now+h[i];//      std::cout<<now.to_string(p)<<"\n";        now=now/2;    }//  fo(i,1,cnt) std::cout<<h[i].to_string(p)<<"\n";    std::cout<<now.to_string(p*6/5)<<"\n";    return 0;}

【NOI 2016 循环之美】

考场上写这题顶多O(nm) 24pts

找规律什么的我可不擅长。

小学老师曾经教过你们,什么时候分数是有限小数呢?当分母是2或者5的时候~

如果你足够机智能YY出来或者打表大力找规律,可以发现这样一个事实。

ans=ni=1mj=1[(i,j)==1][(j,k)==1]

卧槽反演啊老大哥。

繁衍一发得到
ans=ni=1[(i,k)==1]μ(d)ndmdj=1[(j,k)==1]

把后面一坨记为f[md]

你又发现后面这一坨很好算。f[x]=xkf[k]+f[xmodk]

为什么呢?因为辗转相减法就是如此神奇。

蛤蛤。84pts。不做了。滚回家睡觉…

//NOI 2016 循环之美#include<bits/stdc++.h>#define LL long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(int i=j;i<=k;i++)using namespace std;const int mxn=20000005;LL ans;int n,m,k;bool vis[mxn];int pri[mxn],miu[mxn],f[2005];inline int gcd(int x,int y) {if(x%y==0) return y;return gcd(y,x%y);}inline void init(int n){    miu[1]=1;    fo(i,2,n)    {        if(!vis[i]) pri[++pri[0]]=i,miu[i]=-1;        for(int j=1;j<=pri[0] && (LL)i*pri[j]<=n;j++)        {            vis[i*pri[j]]=1;            if(i%pri[j]==0) break;            miu[i*pri[j]]=-miu[i];        }    }    fo(i,1,k)    {        f[i]=f[i-1];        if(gcd(i,k)==1) f[i]++;    }}inline int F(int x){    return (LL)x/k*f[k]+f[x%k];}int main(){    scanf("%d%d%d",&n,&m,&k);    init(n);    fo(i,1,n) if(gcd(i,k)==1)      ans=(ans+(LL)miu[i]*(n/i)*F(m/i));    printf("%lld\n",ans);    return 0;}

【NOI 2016 网格】
虽然写过一发正解,但是太难写了吧…

大力(手玩)观察一下发现答案只有4个。-1,0,1,2。

把好点连接一下,就可以用判割点的操作了。这个也不难看出来。

但是我也不会缩图什么的操作。

那就暴力tarjan判一发,常数优可以get56分。可是我常数不优,52pts。

然后c==0可以手玩几组出解,再拿4pts。
然后c==1可以手玩出解,但是麻烦。我特判了将近30行,就为了额外的4pts。

强迫症福音,60pts

//NOI 2016 网格 #include<bits/stdc++.h>#define LL long long#define p(i,j) (i-1)*m+(j)#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=1000005;bool flag;bool vis[mxn];int n,m,c,T,tim,cnt,num;int dx[5]={0,-1,0,0,1};int dy[5]={0,0,1,-1,0};int dfn[mxn],low[mxn],head[mxn];struct edge {int to,next;} f[mxn<<2];inline int read(){    int x=0;char ch=getchar();    while(ch<'0'||ch>'9') ch=getchar();    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();    return x;}inline void add(int u,int v){    f[++cnt].to=v,f[cnt].next=head[u],head[u]=cnt;    f[++cnt].to=u,f[cnt].next=head[v],head[v]=cnt;}inline void dfs(int u,int fa){    int son=0;bool now=0;    dfn[u]=low[u]=(++tim);    for(int i=head[u];i;i=f[i].next)    {        int v=f[i].to;        if(v==fa) continue;        if(!dfn[v])        {            son++;            dfs(v,u),low[u]=min(low[u],low[v]);            if(dfn[u]<=low[v]) now=1;        }         else low[u]=min(low[u],dfn[v]);    }    if(!fa && son==1) now=0;    flag|=now;}inline bool check(){    int i,j,k;    fo(i,1,n) fo(j,1,m) if(!vis[p(i,j)])    {        fo(k,1,4)        {            int nx=i+dx[k],ny=j+dy[k];            if(nx>=1 && nx<=n && ny>=1 && ny<=m)              if(!vis[p(nx,ny)]) return 1;        }        return 0;    }}int main(){    int i,j,x,y;    T=read();    while(T--)    {        flag=num=cnt=tim=0;        n=read(),m=read(),c=read();        if(!c)        {            if((LL)n*m<=2) {puts("-1");continue;}            if(n==1 || m==1) {puts("1");continue;}            puts("2");continue;        }        if(c==1)        {            x=read(),y=read();            if((LL)n*m-c<=1) {puts("-1");continue;}            if((LL)n*m==3)            {                if(n==1 && (y==1 || y==3)) {puts("-1");continue;}                if(m==1 && (x==1 || x==3)) {puts("-1");continue;}            }            if(n==1)            {                if(y==1 || y==m) {puts("1");continue;}                else {puts("0");continue;}            }            if(m==1)            {                if(x==1 || x==n) {puts("1");continue;}                else {puts("0");continue;}            }            if(n==2 || m==2) {puts("1");continue;}            if(x==1 && y==2) {puts("1");continue;}            if(x==2 && y==1) {puts("1");continue;}            if(x==1 && y==m-1) {puts("1");continue;}            if(x==2 && y==m) {puts("1");continue;}            if(x==n-1 && y==1) {puts("1");continue;}            if(x==n && y==2) {puts("1");continue;}            if(x==n-1 && y==m) {puts("1");continue;}            if(x==n && y==m-1) {puts("1");continue;}            puts("2");continue;        }        fo(i,1,n) fo(j,1,m) vis[p(i,j)]=0;        fo(i,1,c) x=read(),y=read(),vis[p(x,y)]=1;        if(n*m-c<=1) {puts("-1");continue;}        if(n*m-c==2 && check()) {puts("-1");continue;}        fo(i,1,n) fo(j,1,m) head[p(i,j)]=dfn[p(i,j)]=low[p(i,j)]=0;        fo(i,1,n) fo(j,1,m) if(!vis[p(i,j)])        {            x=i,y=j+1;            if(x<=n && y<=m && !vis[p(x,y)])              add(p(i,j),p(x,y));            x=i+1,y=j;            if(x<=n && y<=m && !vis[p(x,y)])              add(p(i,j),p(x,y));        }        fo(i,1,n) fo(j,1,m) if(!dfn[p(i,j)] && !vis[p(i,j)])        {            num++;            if(num>=2) break;            dfs(p(i,j),0);        }        if(num>=2) {puts("0");continue;}        if(flag) puts("1");else puts("2");    }    return 0;}/*12 3 11 2*/

【NOI 2016 旷野大计算】

1~5的点就取绝对值不太会,可以get46分,二进制拆分自己check出来没毛病,但是还是挂了…所以只能拿一个平均分都不到的分…后面的我也玩不动了。

把第六个点的手写check放在这,希望dalao可以帮帮忙

//checker#include<bits/stdc++.h>#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=5005;int x[mxn];int main(){    freopen("nodes6.out","w",stdout);    int i,j;    scanf("%d",&x[1]);//    printf("I\n");    fo(i,2,32)    {        x[i]=x[1]>>(i-1); //       printf("> 1 %d\n",i-1);    }    fo(i,33,63)    {        x[i]=x[i-31]<<(i-32); //       printf("< %d %d\n",i-31,i-32);    }    fo(i,64,94)    {        x[i]=-x[i-31]; //       printf("- %d\n",i-31);    }    x[95]=x[1]+x[64];//printf("+ 1 64\n");    fo(i,96,125)    {        x[i]=(x[i-63]+x[i-31]);  //      printf("+ %d %d\n",i-63,i-31);    }    int cnt=30,tmp=125;    fo(i,126,156)    {//        printf("> %d %d\n",tmp,cnt);        x[i]=x[tmp]>>cnt;        tmp--,cnt--;    } //   puts("O 32"); //   fo(i,126,156) printf("O %d\n",i);    printf("ANS\n\n");    printf("%d",x[32]);    fo(i,126,156) printf("%d",x[i]);    return 0;}

【NOI 2016 优秀的拆分】
hash 95分,喜闻乐见

//NOI 2016 优秀的拆分 #include<bits/stdc++.h>#define LL unsigned long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=2005;char s[mxn];int n,m,T;LL z[mxn],pw[mxn];int main(){    int i,j,k;    pw[0]=1;    fo(i,1,2000) pw[i]=pw[i-1]*27;    scanf("%d",&T);    while(T--)    {        LL ans=0;        scanf("%s",s+1);        n=strlen(s+1);        fo(i,1,n) z[i]=z[i-1]*27+s[i]-'a';        fo(i,2,n-2)        {            int lef=0,rig=0;            for(j=1;j<=i/2;j++)            {                int one=i-2*j+1;                int two=one+j-1;                int thr=two+1;                int fou=i;                if(z[two]-z[one-1]*pw[j]==z[fou]-z[thr-1]*pw[j])                  lef++;            }            for(j=1;j<=(n-i)/2;j++)            {                int one=i+1;                int two=one+j-1;                int thr=two+1;                int fou=thr+j-1;                if(z[two]-z[one-1]*pw[j]==z[fou]-z[thr-1]*pw[j])                  rig++;            }            ans=ans+(LL)lef*rig;//          printf("ans[%d]=%d\n",i,lef*rig);        }        cout<<ans<<endl;    }    return 0;}

【NOI 2014 动物园】
这不是暴力…唉我的脑子真是瓦特了。

//NOI 2014 动物园 #include<bits/stdc++.h>#define LL long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mod=1000000007;const int mxn=1000005;int n,T,len;char s[mxn];//vector <int> son[mxn];int fail[mxn],num[mxn],dep[mxn];int main(){    int i,j;    scanf("%d",&T);    while(T--)    {        LL ans=1;        scanf("%s",s+1);        len=strlen(s+1);        M(fail),M(num),M(dep);        fail[1]=0,dep[1]=1;        for(i=2,j=0;i<=len;i++)        {            while(j && s[j+1]!=s[i]) j=fail[j];            if(s[j+1]==s[i]) j++;            fail[i]=j;            dep[i]=dep[j]+1;        }        for(i=2,j=0;i<=len;i++)        {            while(j && s[j+1]!=s[i]) j=fail[j];            if(s[j+1]==s[i]) j++;            while(j>i/2) j=fail[j];            num[i]=dep[j];        }        fo(i,1,len)          ans=(LL)ans*(num[i]+1)%mod;        printf("%lld\n",ans);    }    return 0;}/*1abcababc*/
原创粉丝点击