Educational Codeforces Round 78

A   Shuffle Hashing

把第二个串从头到尾扫一遍,挨个判断与第一个串长度一样的子串是否合法即可

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

int T,flag,a[50],cnt;
char p[10005],h[10005];

int main()
{
    scanf("%d",&T);
    while (T--) {
        memset(a,0,sizeof(a));
        flag=cnt=0;
        scanf("%s",p);
        scanf("%s",h);
        int len1=strlen(p);
        int len2=strlen(h);
        for (int i=0;i<len1;i++) a[p[i]-'a']++;
        for (int i=0;i<len1;i++) a[h[i]-'a']--;
        for (int i=0;i<26;i++) cnt+=a[i]==0;
        flag|=(cnt==26);
        for (int i=len1;i<len2;i++) {
            int t=h[i]-'a';
            if (a[t]==0) cnt--,a[t]--;
            else a[t]--,cnt+=a[t]==0;
            t=h[i-len1]-'a';
            if (a[t]==0) cnt--,a[t]++;
            else a[t]++,cnt+=a[t]==0;
            flag|=(cnt==26);
        }
        if (flag) puts("YES");
        else puts("NO");
    }
    
    return 0;
}

 

B . A and B

找找规律,找到第一个前i个数之和大于a,b只差的i,再看看奇偶,讨论一下,+0/+1/+2

前100答案如下

1 : 1
2 : 3
3 : 2
4 : 3
5 : 5
6 : 3
7 : 5
8 : 4
9 : 5
10 : 4
11 : 5
12 : 7
13 : 5
14 : 7
15 : 5
16 : 7
17 : 6
18 : 7
19 : 6
20 : 7
21 : 6
22 : 7
23 : 9
24 : 7
25 : 9
26 : 7
27 : 9
28 : 7
29 : 9
30 : 8
31 : 9
32 : 8
33 : 9
34 : 8
35 : 9
36 : 8
37 : 9
38 : 11
39 : 9
40 : 11
41 : 9
42 : 11
43 : 9
44 : 11
45 : 9
46 : 11
47 : 10
48 : 11
49 : 10
50 : 11
51 : 10
52 : 11
53 : 10
54 : 11
55 : 10
56 : 11
57 : 13
58 : 11
59 : 13
60 : 11
61 : 13
62 : 11
63 : 13
64 : 11
65 : 13
66 : 11
67 : 13
68 : 12
69 : 13
70 : 12
71 : 13
72 : 12
73 : 13
74 : 12
75 : 13
76 : 12
77 : 13
78 : 12
79 : 13
80 : 15
81 : 13
82 : 15
83 : 13
84 : 15
85 : 13
86 : 15
87 : 13
88 : 15
89 : 13
90 : 15
91 : 13
92 : 15
93 : 14
94 : 15
95 : 14
96 : 15
97 : 14
98 : 15
99 : 14
100 : 15

详见代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;

int T,a,b,t,ans;

int main()
{
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&a,&b);
        t=abs(a-b);
        int x=sqrt(t*2);
        if (x*(x+1)/2<t) x++;
        if (x&1) {
            if ((x*(x+1)/2-t)&1) ans=x+2;
            else ans=x;
        }else {
            if ((x*(x+1)/2-t)&1) ans=x+1;
            else ans=x;
        }
        printf("%d\n",ans);
    }
    
    return 0;
}

Berry Jam

枚举左边剩几个,求右边最多剩几个,懒得处理下标为负的情况,用了map

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
using namespace std;

int T,n,ans,a[100005],b[100005];
map <int,int> s;

int main()
{
    scanf("%d",&T);
    while (T--) {
        scanf("%d",&n);
        ans=n+n;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        s.clear();
        for (int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            if (a[i]==2) a[i]=-1;
            a[i]+=a[i-1];
        }
        for (int i=1;i<=n;i++) {
            scanf("%d",&b[i]);
            if (b[i]==2) b[i]=-1;
        }
        for (int i=n+1;i>=1;i--) {
            b[i]+=b[i+1];
            s[b[i]]=i;
        }
        for (int i=0;i<=n;i++) {
            if (s[-a[i]]) ans=min(ans,n-i+s[-a[i]]-1);
        }
        printf("%d\n",ans);
    }
    
    return 0;
}

 D Segment Tree

枚举所以相交的边,一共n-1条,多了少了都不行,用set处理了一下,然后并查集判断是否为一棵树。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
#define mp make_pair
#define x first
#define y second

const int N=1e6+7;
typedef pair<int,int> pii;

struct P {
    int l,r;
    bool operator < (const P&b) const {
        return l<b.l;
    }
}a[N];

int fa[N],Cnt,cnt,n;
set <pii> s;
vector <pii> b;

int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y) {
    int fx=find(x),fy=find(y);
    if (fx^fy) {
        Cnt++;fa[fx]=fy;
    }
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) {
        scanf("%d%d",&a[i].l,&a[i].r);
        b.push_back(mp(a[i].l,i));
        b.push_back(mp(a[i].r,i));
    }
    sort(b.begin(),b.end());
    for (int i=1;i<=n;i++) fa[i]=i;
    for (int i=0;i<b.size();i++) {
        int u=b[i].x,k=b[i].y;
        if (s.count(b[i])) {
            s.erase(b[i]);continue;
        }
        for (auto t : s) {
            if (t.x>a[k].r) break;
            merge(k,t.y);
            cnt++;
        }
        if (cnt>=n) break;
        s.insert(mp(a[k].r,k));
    }
    if (cnt!=n-1||Cnt!=n-1) puts("NO");
    else puts("YES");
    return 0;
}

F. Cards

简单学了学第二类斯特林数,然后就化简呗,先贴码,公式==再补。

 

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

typedef long long ll;
const ll mod=998244353;
const int N=5005;
int n,m,k;
ll ans,c[N],fac[N],s[N][N];


ll Pow(ll x,ll y) {
    ll ret=1;
    while (y) {
        if (y&1) ret=ret*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ret;
}

ll inv(ll x) {return Pow(x,mod-2);}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    s[0][0]=1;fac[0]=1;c[0]=1;
    for (int i=1;i<=k;i++) {
        for (int j=1;j<=k;j++) {
            s[i][j]=(s[i-1][j-1]+s[i-1][j]*j)%mod;
        }
        fac[i]=fac[i-1]*i%mod;
        c[i]=c[i-1]*(n-i+1)%mod*inv(i)%mod;
    }
    for (int j=0;j<=k;j++) {
        ans=(ans+s[k][j]*fac[j]%mod*c[j]%mod*Pow(inv(m),j))%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2019-12-22 21:27  yanglang  阅读(286)  评论(1编辑  收藏  举报