ContestHunter暑假欢乐赛 SRM 09(TJM大傻逼选手再创佳绩)

  T1 f[i]为前i页最少被撕几页,用二分转移就行了,答案为ans=min(f[i]+(n-i)); 不知道为什么写挂了嗯 二分的l初始应该是0

  T2 数位DP f[i][1/0][1/0][1/0]表示第i位第一个数是1/0,第二个数是1/0,有无进位的方案数  转移非常恶心。。。  没看见正整数结果WA了,有想到x<y的trick但是觉得这方法应该不用理这个,结果是要的...其实也不知道这做法到底对不对,补题的时候看看吧 事实证明是可以的 

  贴一波代码,好像大家做的方法都不一样  CYC的方法好喵喵哇,太强辣~ 我人比较傻逼没法治的唉(LLQ也是这种写法 都炒鸡强哇%%%

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long 
using namespace std;
const int maxn=500010,inf=1e9;
ll n,m,x,y,z,tot,cnt,digit[maxn];
ll f[2333][2][2][2],ans;
void read(ll &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
int main()
{
    read(n);read(m);bool flag=0;
    if(n==m)flag=1;
    ll x=m,cnt2=0;
    while(n){digit[++cnt]=n&1;n>>=1;}
    while(x){cnt2++;x>>=1;}
    if(cnt2>cnt)
    {
        puts("0");
        return 0;
    }
    f[0][0][0][0]=1;
    for(int i=1;i<=cnt;i++)
    {
        ll now=m&(1ll<<(i-1));
        if(now)
        {
            if(digit[i])
            {
                f[i][1][0][0]+=f[i-1][1][0][0]+f[i-1][0][1][0]+f[i-1][0][0][0]+f[i-1][0][0][1];
                f[i][0][1][0]+=f[i-1][1][0][0]+f[i-1][0][1][0]+f[i-1][0][0][0]+f[i-1][0][0][1];
                if(i==cnt)ans=f[i][1][0][0]+f[i][0][1][0];
            }
            else
            {
                f[i][1][0][1]+=f[i-1][1][1][1]+f[i-1][1][0][1]+f[i-1][0][1][1]+f[i-1][0][0][1];
                f[i][0][1][1]+=f[i-1][1][1][1]+f[i-1][1][0][1]+f[i-1][0][1][1]+f[i-1][0][0][1];
            }
        }
        else
        {
            if(digit[i])
            {
                f[i][1][1][1]+=f[i-1][1][1][1]+f[i-1][1][0][1]+f[i-1][0][1][1];
                f[i][0][0][0]+=f[i-1][1][1][1]+f[i-1][1][0][1]+f[i-1][0][1][1];
                if(i==cnt)ans=f[i][0][0][0];
            }
            else
            {
                f[i][1][1][1]+=f[i-1][1][0][0]+f[i-1][0][1][0]+f[i-1][0][0][0];
                f[i][0][0][0]+=f[i-1][1][0][0]+f[i-1][0][1][0]+f[i-1][0][0][0];
            }
        }
    }
    printf("%lld
",flag?ans-2:ans);
    return 0;
}
View Code

  T3 1s O(500^3)居然是可以过的TAT

    f[L][R]表示[L..R]这个区间的最小次数。

      暴力是个O(N^4)的,枚举两个区间,哈希判回文。。。不知道哪里又写挂了只拿了第一部分的暴力分

    O(N^3)的也很好想。。可以枚举[L..R]中的一点x,若a[R]==a[x],那么可以把[X+1..R-1]消剩下一个回文,然后把R和这个回文和X一起消掉,则有f[L][R]=min(f[L][R],f[L][X-1]+f[X+1][R-1]);

    码力太有问题了...可能创下了最快补完题记录,真的是每题都离正解一步...

    这已经不是一次两次了...不想着找原因老是觉得下次注意就行是不会解决的,这么粗糙的人不经过打磨也绝无可能取得好成绩,这段时间要尽力静下心改变自己了

    希望没有下一次

    

原文地址:https://www.cnblogs.com/Sakits/p/7282176.html