考前XJB打暴力系列

【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;
}
/*
1
2 3 1
1 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;
}
/*
1
abcababc
*/
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值