10.4 Morning


居然得到了rk3,真的是欧气爆表啊今天


Problem A.r

【题目描述】

10.4清北刷题记-LMLPHP

【输入描述】

第一行一个整数T,代表测试数据的组数。 接下来T行每行一个日期。

【输出描述】

T行每行一个字符串,如果这个日期是伟大的,那么输出 Niubi,否则输出Haixing。

【输入输出样例】

【input】

2

1926-08-19

1926-08-14

【output】

Niubi

Niubi

【数据范围】

10.4清北刷题记-LMLPHP


【代码实现】

博主个人的满分代码

#include<cstdio>
#include<cctype>
#include<cmath>
const int md[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int readin()
{
    char ch;int res=0;
    for(;!(isdigit(ch));ch=getchar());
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
bool spy[10000];
struct date{
    int y,m,d;
}day,qwq;
inline bool cmp(date A,date B)
{
    if(A.y!=B.y) return A.y<B.y;
    if(A.m!=B.m) return A.m<B.m;
    return A.d<B.d;
}
int solve(date a,date b)
{
    if(cmp(b,a)) return solve(b,a);
    int res=0;date cnt;cnt.m=2;cnt.d=29;
    for(register int i=a.y;i<=b.y;i++)
    {
        cnt.y=i;
        if(spy[i]&&cmp(a,cnt)&&cmp(cnt,b)) res++;
    }
    while(cmp(a,b)&&a.y<b.y-1) a.y++,res+=365;
    while(cmp(a,b))
    {
        a.d++;res++;
        if(a.d>md[a.m]) a.d=1,a.m++;
        if(a.m>12) a.m=1,a.y++;
    }
    return res;
}
bool pd(int p)
{
    if(p==0) return true;
    if(p==1) return false;
    for(register int i=2;i<=sqrt(p);i++)
      if(p%i==0) return false;
    return true;
}
int main()
{
    freopen("r.in","r",stdin);
    freopen("r.out","w",stdout);
    int T=readin();day.y=1926;day.m=8;day.d=17;
    for(register int i=0;i<=9999;i++)
      if((i%400==0)||(i%4==0&&i%100!=0)) spy[i]=true;
    for(register int i=1;i<=T;i++)
    {
        qwq.y=readin();qwq.m=readin();qwq.d=readin();
        if(pd(solve(qwq,day))) puts("Niubi");
        else puts("Haixing");
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

Problem B. q

【题目描述】

10.4清北刷题记-LMLPHP

【输入描述】

第一行一个整数N代表基佬的对数

【输出描述】

一行一个整数代表答案对10^9 + 7取模之后的结果。

【输入输出样例】

【input】

2

【output】

2

【input】

3

【output】

32

【数据范围】

10.4清北刷题记-LMLPHP


给出题解:围坐问题


【代码实现】

20分代码

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

using namespace std;

typedef long long ll;

int read()
{
    int x = 0;
    int k = 1;
    char c = getchar();
    while (c > '9' || c < '0')
        if (c == '-') c = getchar(), k = -1;
        else c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48),
        c = getchar();
    return x * k;
}

int n;
int cnt = 0;
int ans = 0;
int a[303030];
int b[303030];
int vis[303030];

void dfs(int las, int sum)
{
    if (sum == cnt)
    {
        if (a[b[cnt]] != a[b[1]])
            ++ans;
        return;
    }
    if (cnt < sum) return;

    for (int i = 1; i <= cnt; ++i)
    {
        if (vis[i] || a[i] == a[las]) continue;
        vis[i] = 1;
        b[sum + 1] = i;
        dfs(i, sum + 1);
        vis[i] = 0;
    }
}

int main()
{
    freopen("q.in", "r", stdin);
    freopen("q.out", "w", stdout);
    n = read();
    a[0] = -123223;
    ans = 0;
    cnt = 0;
    b[1] = 1;
    vis[1] = 1;
    for (int i = 1; i <= n; ++i)
        a[++cnt] = i, a[++cnt] = i;
    dfs(1, 1);
    printf("%d\n", ans % 1000000007);
    return 0;

}

40分代码

//爆搜挂机一小时,打表才能出奇迹
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define RI register int
using namespace std;
typedef long long ll;

#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))

const int inf = 1e9 + 7;
const int MAXN = 100000 + 5;

inline void read(ll &x)
{
    x = 0;
    bool flag = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')   flag = 1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    if(flag)    x *= -1;
}

ll ans[MAXN],n;

int main()
{
    freopen("q.in", "r", stdin);
    freopen("q.out", "w", stdout);
    ans[1] = 0,ans[2] = 2,ans[3] = 32,ans[4] = 1488,ans[5] = 112512,ans[6] = 12771840,ans[7] = 2036229120,ans[8] = 434469611520,ans[9] = 119619533537280,ans[10] = 41303040523960320;
    ans[11] = 32666250,ans[12] = 339045394,ans[13] = 708481754,ans[14] = 917300196,ans[15] = 137957508,ans[16] = 361667305,ans[17] = 167140124,ans[18] = 825728184,ans[19] = 266913721,ans[20] = 418434649;
    for(int i = 1;i <= 20;i ++) ans[i] = ans[i] % inf;
    read(n);
    cout << ans[n] << endl;
    fclose(stdin);
    fclose(stdout);
    return 0;
}

博主的70分代码

//运算过程中可能会出现爆int的数,所以不光要一步一%,更需要开long long
//要用线性求逆元、组合数的递推公式(线性地求每一行)
//最后答案可能是负数,所以一定不要忘了加上mod再%一遍啊qaq
#include<cstdio>
#define N 200001
#define mod 1000000007
int n;
long long a[N],b[N<<1],c[N],A[N];
void init()
{
    A[1]=1;
    for(int i=2;i<=n;i++) A[i]=((mod-(mod/i))*A[mod%i]%mod+mod)%mod;
    c[0]=1;
    for(int i=1;i<=n;i++) c[i]=(((c[i-1]*(n-i+1)%mod)*A[i]))%mod;
}
long long p,ans;
int main()
{
    freopen("q.in","r",stdin);
    freopen("q.out","w",stdout);
    scanf("%d",&n);a[0]=b[0]=c[0]=1;
    for(register int i=1;i<=n;i++) a[i]=(a[i-1]<<1)%mod;
    for(register int i=1;i<=(n<<1);i++) b[i]=(b[i-1]*((long long)i))%mod;
    init();
    for(register int i=0;i<=n;i++)
    {
        if(i&1) ans=(ans-(((a[i]*b[(n<<1)-i-1])%mod)*c[i])%mod)%mod;
        else ans=(ans+(((a[i]*b[(n<<1)-i-1])%mod)*c[i])%mod)%mod;
    }
    if(n!=1) printf("%lld",ans%mod);
    else puts("0");
    fclose(stdin);
    fclose(stdout);
    return 0;
}

博主的100分代码(发下源程序来瞬间改成正解)

#include<cstdio>
#define N 200001
#define mod 1000000007
int n;
long long a[N],b[N<<1],c[N],A[N];
void init()
{
    A[1]=1;
    for(int i=2;i<=n;i++) A[i]=((mod-(mod/i))*A[mod%i]%mod+mod)%mod;
    c[0]=1;
    for(int i=1;i<=n;i++) c[i]=(((c[i-1]*(n-i+1)%mod)*A[i]))%mod;
}
long long p,ans;
int main()
{
    freopen("q.in","r",stdin);
    freopen("q.out","w",stdout);
    scanf("%d",&n);a[0]=b[0]=c[0]=1;
    for(register int i=1;i<=n;i++) a[i]=(a[i-1]<<1)%mod;
    for(register int i=1;i<=(n<<1);i++) b[i]=(b[i-1]*((long long)i))%mod;
    init();
    for(register int i=0;i<=n;i++)
    {
        if(i&1) ans=(ans-(((a[i]*b[(n<<1)-i-1])%mod)*c[i])%mod)%mod;
        else ans=(ans+(((a[i]*b[(n<<1)-i-1])%mod)*c[i])%mod)%mod;
    }
    if(n!=1) printf("%lld",(ans+mod)%mod);
    else puts("0");
    fclose(stdin);
    fclose(stdout);
    return 0;
}

Problem C. y

10.4清北刷题记-LMLPHP

【输入格式】

第一行一个字符串s1。

第二行一个字符串s2。

第三行一个整数K,代表操作的次数。

接下来k行,每行第一个整数opt。如果opt = 1,代表第一种操作,接下来给出两个整数l, r,代表询问的区间;如果opt = 2,代表第二种操作,接下来给出两个整数l, r,代表操作的区间。

【输出格式】

对于每一次第一种操作,输出一行代表答案。

【输入输出样例】

【input】

10101

10

3

1 1 5

2 1 5

1 2 4

【output】

2

1

【数据范围】

10.4清北刷题记-LMLPHP


【代码实现】

30分代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int k,opt,l,r,len,num;
char s1[100005],s2[25];
char p[100005];
void pre()
{
    p[1]=0;
    int j=0;
    for(int i=1;i<len;i++)
    {
        while(j>0&&s2[j+1]!=s2[i+1])
          j=p[j];
        if(s2[j+1]==s2[i+1])
          j++;
        p[i+1]=j;
    }
    return;
}
void kmp(int l,int r)
{
    int j=0;
    for(int i=l-1;i<r;i++)
    {
        while(j>0&&s2[j+1]!=s1[i+1])
          j=p[j];
        if(s2[j+1]==s1[i+1])
          j++;
        if(j==len)
        {
            num++;
            j=p[j];
        }
    }
    return;
}
void two(int l,int r)
{
    if(l==r)
    {
        s1[l]='1'-s1[l]+'0';
        return;
    }
    int mid=(l+r)/2;
    two(l,mid);
    two(mid+1,r);
    return;
}
int main()
{
    freopen("y.in","r",stdin);
    freopen("y.out","w",stdout);
    scanf("%s%s",s1+1,s2+1);
    len=strlen(s2+1);pre();
    scanf("%d",&k);
    while(k--)
    {
        scanf("%d%d%d",&opt,&l,&r);
        if(opt==1)
        {
            num=0;
            kmp(l,r);
            printf("%d\n",num);
        }
        if(opt==2)
          two(l,r);
    }
    return 0;
}

40分代码之线段树

#include<cstdio>
#include<cstring>
#define rg register
#define ci const int
#define cl const long long int

namespace IO {
    char buf[110];
}

template <typename T>
inline void qr(T &x) {
    char ch=getchar(),lst=' ';
    while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
    while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    if(lst == '-') x=-x;
}

template <typename T>
inline void write(T x,const char aft,const bool pt) {
    if(x < 0) {putchar('-');x=-x;}
    rg int top=0;
    do {
        IO::buf[++top]=x%10+'0';x/=10;
    } while(x);
    while(top) putchar(IO::buf[top--]);
    if(pt) putchar(aft);
}

template <typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template <typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template <typename T>
inline T mabs(const T x) {return x < 0 ? -x : x;}

template <typename T>
inline void mswap(T &a,T &b) {
    T temp=a;a=b;b=temp;
}

const int maxn = 100010;

int n,m;
char s1[maxn],s2[maxn];

namespace xiagao{
const int maxt = 400010;
#define MU s1
int frog[maxt];
bool lazy[maxt];

void build(ci l,ci r,ci p) {
    if(l>r) return;
    if(l==r) {frog[p]=MU[l]-'0';return;}
    int mid=(l+r)>>1,dp=p<<1,ddp=dp|1;
    build(l,mid,dp);build(mid+1,r,ddp);
    frog[p]=frog[dp]+frog[ddp];
}

inline void free(ci l,ci r,ci mid,ci p,ci dp,ci ddp) {
    if(!lazy[p])    return;
    frog[dp]=mid-l+1-frog[dp];frog[ddp]=r-mid-frog[ddp];
    lazy[ddp]=!lazy[ddp];lazy[dp]=!lazy[dp];lazy[p]=false;
}

void change(ci l,ci r,ci p,ci aiml,ci aimr) {
    if(l>r) return;
    if(l>aimr||r<aiml)  return;
    if(l>=aiml&&r<=aimr) {frog[p]=r-l+1-frog[p];lazy[p]=!lazy[p];return;}
    int mid=(l+r)>>1,dp=p<<1,ddp=dp|1;
    free(l,r,mid,p,dp,ddp);
    change(l,mid,dp,aiml,aimr);change(mid+1,r,ddp,aiml,aimr);
    frog[p]=frog[dp]+frog[ddp];
}

int ask(ci l,ci r,ci p,ci aiml,ci aimr) {
    if(l>r) return 0;
    if(l>aimr||r<aiml)  return 0;
    if(l>=aiml&&r<=aimr) return frog[p];
    int mid=(l+r)>>1,dp=p<<1,ddp=dp|1;
    free(l,r,mid,p,dp,ddp);
    return ask(l,mid,dp,aiml,aimr)+ask(mid+1,r,ddp,aiml,aimr);
}

int qwq() {
    build(1,n,1);
    rg int k=0;qr(k);
    rg int a,b,c;
    while(k--) {
        a=b=c=0;qr(a);qr(b);qr(c);
        if(a == 1) {int _ans=ask(1,n,1,b,c);if(s2[1] == '1') write(_ans,'\n',true);else write(c-b+1-_ans,'\n',true);}
        else change(1,n,1,b,c);
    }
    return 0;
#undef MU
}
}

int main() {
    freopen("y.in","r",stdin);
    freopen("y.out","w",stdout);
    scanf("%s\n%s",s1+1,s2+1);
    n=strlen(s1+1),m=strlen(s2+1);
    if(m == 1) return xiagao::qwq();
    rg int k=0;qr(k);
    rg int a,b,c;
    while(k--) {
        a=b=c=0;qr(a);qr(b);qr(c);
        if(a == 1) {
            rg int _ans=0;
            c-=m;++c;
            for(rg int i=b;i<=c;++i) {
                bool _judge=true;
                for(rg int h=1;h<=m;++h) {
                    if(s1[i+h-1] != s2[h]) {_judge=false;break;}
                }
                if(_judge) ++_ans;
            }
            write(_ans,'\n',true);
        }
        else {
            for(rg int i=b;i<=c;++i) {
                if(s1[i] == '0') s1[i]='1';
                else s1[i]='0';
            }
        }
    }
    return 0;
}

50分代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,len1,len2,ans=0,l,a,b,c,opt;
int next1[100005];
char s1[100006],now[100005];
char s2[100005];
inline void get_next() {
    int t1=0,t2;next1[0]=t2=-1;while(t1<len2)
    if(t2==-1||s2[t1]==s2[t2])next1[++t1]=++t2;else t2=next1[t2];
}
inline void kmp() {
    int t1=0,t2=0;while(t1<len1) {if(t2==-1 || now[t1]==s2[t2])t1++,t2++;
        else t2=next1[t2];if(t2==len2) ans++,t2=next1[t2];}
}
int main() {
    freopen("y.in","r",stdin);
    freopen("y.out","w",stdout);
    cin>>s1>>s2;len2=strlen(s2);get_next();
    cin>>k;
    while(k--){ans=0;
        cin>>opt>>a>>b;
        if(opt==2){
            for(int i=a-1;i<b;i++)if(s1[i]=='1')s1[i]='0';else s1[i]='1';
        }else {int j=0;
            for(int i=a-1;i<b;i++)now[j++]=s1[i];len1=j;kmp();
            cout<<ans<<endl;}
    }
    return 0;
}

100分代码(线段树)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int maxn=100010;
const int maxm=25;

int n,m,k,v,inv,up;

char s1[maxn],s2[maxm];

struct node
{
    int pre[maxm],suf[maxm];
    int ans,invans;
    bool rev;

    node()
    {
        memset(pre,-1,sizeof(pre));
        memset(suf,-1,sizeof(suf));
        rev = false;
        ans=invans=0;
    }
}z[maxn<<2|1];

node operator+(const node &l,const node &r)
{
    node c;
    for (int a=1;a<m;a++)
        if (l.pre[a] == -1)
        {
            a--;
            for (int b=1;a+b<m;b++)
                if (r.pre[b]!=-1) c.pre[a+b] = (l.pre[a]<<b)|r.pre[b];
                else break;
            break;
        }
        else c.pre[a] = l.pre[a];

    for (int a=1;a<m;a++)
        if (r.suf[a] == -1)
        {
            a--;
            for (int b=1;a+b<m;b++)
                if (l.suf[b]!=-1) c.suf[a+b] = (l.suf[b]<<a)|r.suf[a];
                else break;
            break;
        }
        else c.suf[a] = r.suf[a];

    c.ans = l.ans+r.ans;
    for (int a=1;a<m;a++)
        if (l.suf[a]!=-1 && r.pre[m-a]!=-1 && ((l.suf[a]<<(m-a))|r.pre[m-a])==v) c.ans++;

    c.invans = l.invans+r.invans;
    for (int a=1;a<m;a++)
        if (l.suf[a]!=-1 && r.pre[m-a]!=-1 && ((l.suf[a]<<(m-a))|r.pre[m-a])==inv) c.invans++;

    return c;
}

void update(int rt)
{
    z[rt] = z[rt<<1] + z[rt<<1|1];
}

void color(int rt)
{
    z[rt].rev ^= true;
    swap(z[rt].ans,z[rt].invans);
    for (int a=1;a<m;a++)
    {
        if (z[rt].suf[a]!=-1) z[rt].suf[a]^=(1<<a)-1;
        if (z[rt].pre[a]!=-1) z[rt].pre[a]^=(1<<a)-1;
    }
}

void push_col(int rt)
{
    if (z[rt].rev)
    {
        color(rt<<1);
        color(rt<<1|1);
        z[rt].rev=false;
    }
}

void build(int l,int r,int rt)
{
    if (l==r)
    {
        if (m==1)
        {
            if (s1[l]==v) z[rt].ans=1;
            else z[rt].invans=1;
        }
        z[rt].pre[1]=z[rt].suf[1]=s1[l];
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    update(rt);
}

node query(int l,int r,int rt,int nowl,int nowr)
{
    if (nowl<=l && r<=nowr) return z[rt];
    push_col(rt);
    int m=(l+r)>>1;
    if (nowl<=m)
    {
        if (m<nowr) return query(lson,nowl,nowr)+query(rson,nowl,nowr);
        else return query(lson,nowl,nowr);
    }
    else return query(rson,nowl,nowr);
}

void modify(int l,int r,int rt,int nowl,int nowr)
{
    if (nowl<=l && r<=nowr)
    {
        color(rt);
        return;
    }
    push_col(rt);
    int m=(l+r)>>1;
    if (nowl<=m) modify(lson,nowl,nowr);
    if (m<nowr) modify(rson,nowl,nowr);
    update(rt);
}

int main()
{
    scanf("%s",s1+1);
    scanf("%s",s2+1);
    n=strlen(s1+1);
    m=strlen(s2+1);
    for (int a=1;a<=n;a++)
        s1[a]-='0';
    for (int a=1;a<=m;a++)
        s2[a]-='0';
    for (int a=1;a<=m;a++)
        v=v<<1|s2[a];
    up = (1<<m)-1;
    inv = v^up;
    build(root);
    scanf("%d",&k);
    for (int a=1;a<=k;a++)
    {
        int opt,l,r;
        scanf("%d%d%d",&opt,&l,&r);
        if (opt==1) printf("%d\n",query(root,l,r).ans);
        else modify(root,l,r);
    }

    return 0;
}
10-06 20:11