JNday5-am

T1是一个大组合数取模,用的是线性求逆元,貌似忘了,想了很久,

艰难A掉

T2最大生成树有一个性质,任意两点间的边权最小的边一定是连接两点
间所有路径中最大的(否则可以替换,使最大生成树变大)。
这个题目,其实是求最大生成森林的过程,考虑Kruskal 过程,每合并
两个集合,实际上选的这条边是连接两个集合最大的限重。也就是货
物重量低于这个值,就可以通过这条边在两个集合之间运输,否则这
两个集合就一定至少需要两个仓库。
所以整个kruskal 过程,实际上每次是在求,重量低于多少时可以减少
一个仓库。于是一开始有n 个仓库,把减少仓库的关键点记下来,对
于每个询问二分即可,或者使用lower_bound。

T3
很GG
没听懂
首先不好处理的一点是,一个合法的单词有多种拆分方法。
可以认为从最后一个合法的位置拆分。
但是需要处理。
cool,o 这种情况。
然后用一个trie 树进行计数,详见代码,a 数组是长度为i 的前缀,后
面接j 字母不可能还是前缀的数量。b 数组是长度为i 的前缀,最后一
个字母是j 并且不是词典中的单词的数量。c 数组是长度为i 的后缀,
第一个字母是j 的数量。
合并这三个数组即可。

T1 立方体

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

using namespace std;
const int N = 1e6 + 10;

#define Lgj 1000000007
#define LL long long

LL jc[N], Inv[N], inv[N];
int n, k, my;

inline int read()
{
    int x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + c -'0', c = getchar();
    return x;
}

void before() 
{
    jc[0] = jc[1] = 1; inv[0] = inv[1] = 1; Inv[0] = Inv[1] = 1;
    for(int i = 2; i <= 1000005; ++ i) 
    {
        jc[i] = ( jc[i - 1] % Lgj * i % Lgj ) % Lgj;
        inv[i] = (1LL * (- (Lgj / i) * inv[Lgj %  i])) % Lgj;
        if(inv[i] < 0) inv[i] += Lgj;
        Inv[i] = ( Inv[i - 1] % Lgj * inv[i] % Lgj ) % Lgj;
        if(Inv[i] < 0) Inv[i] += Lgj;
    }
}

LL C(int n,int m) 
{
    LL ret;
    ret = ( (jc[n] % Lgj * Inv[m] % Lgj) % Lgj * Inv[n - m] % Lgj ) % Lgj;
    return ret;
}

int main(int argc, char *argv[]) //这个东西听zjr说貌似能加速,试试呗 
{
    freopen("cube.in", "r", stdin);
    freopen("cube.out", "w", stdout); 
    before();
    n = read();
    k = read();
    for(int i = 1; i <= n; i ++ ) my = read();
    LL answer = C(n, k);
    printf("%I64d\n",answer);
    return 0;
}

 

T2 仓库

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

using namespace std;

typedef long long LL;

int n,m,q;
struct N{
    int x,y,z;
}edge[100005];
int fa[100005];
bool cmp(N a,N b){
    return a.z>b.z;
}
int get(int x){
    return fa[x]==x?x:fa[x]=get(fa[x]);
}

int p[100005],cc,w;

int main(){
    freopen("warehouse.in","r",stdin);
    freopen("warehouse.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);
    }
    for(int i=1;i<=n;i++) fa[i]=i;
    sort(edge+1,edge+m+1,cmp);
    for(int i=1;i<=m;i++){
        if(get(edge[i].x)!=get(edge[i].y)){
            fa[get(edge[i].x)] = edge[i].y;
            p[++cc] = edge[i].z;
        }
    }
    assert(cc == n-1);
    reverse(p+1,p+cc+1);
    while(q--){ 
        scanf("%d",&w);
        int pos = lower_bound(p,p+cc+1,w)-p;
        // printf("# %d\n",pos);
        printf("%d\n",pos);
    }
    return 0;
}

T3 单词

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

using namespace std;
typedef long long LL;
LL mod = 1e9+7;
int n,q;

char s[55];
LL cnt[105];
int a[55][26];
int b[55][26];
int c[55][26];
struct Trie{
    int trie[500050][26];
    int flag[500050];
    int tot;
    void insert(char * s){
        int id = 0;
        for(int i=0;s[i];i++){
            if(trie[id][s[i]-'a']) id = trie[id][s[i]-'a'];
            else id = trie[id][s[i]-'a']=++tot;
        }
        flag[id] ++;
        assert(flag[id] == 1);
    }
    void dfs(int x,int l){
        for(int i=0;i<26;i++){
            if(trie[x][i] == 0 && x){
                a[l][i] ++;
            }
            if(trie[x][i] && x && !flag[trie[x][i]]){
                b[l+1][i] ++;
            }
            if(trie[x][i]) dfs(trie[x][i],l+1);
        }
    }
    void solve1(){
        dfs(0,0);
    }
    void dfs2(int x,int l){
        for(int i=0;i<26;i++){
            if(trie[x][i]){
                c[l+1][i]++;
                dfs2(trie[x][i],l+1);
            }
        }
    }
    void solve2(){
        dfs2(0,0);
    }
}t1,t2;

int main(){
    freopen("word.in","r",stdin);
    freopen("word.out","w",stdout);
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        int L = strlen(s);
        t1.insert(s);
        reverse(s,s+L);
        t2.insert(s);
        cnt[L]++;
    }
    t1.solve1();
    t2.solve2();
    for(int l=1;l<=50;l++){//b
        for(int i=0;i<26;i++){
            assert(c[1][i] == 0 || c[1][i] == 1);
            if(c[1][i]){
                cnt[l]+=b[l][i];
            }
        }
    }
    for(int l1 = 1;l1 <=50;l1++){
        for(int l2 = 1;l2 <=50;l2++){
            for(int i=0;i<26;i++){
                cnt[l1+l2] += a[l1][i]*1LL * c[l2][i];
            }
        }
    }
    int L;
    while(q--){
        scanf("%d",&L);
        printf("%d\n",(int)(cnt[L]%mod));
    }

    return 0;
}

 

posted @ 2017-11-01 21:16  ioioioioioio  阅读(156)  评论(0编辑  收藏  举报