2017.10.23 模拟考试 (题目来自:学大伟业)

来源:互联网 发布:目前淘宝什么好卖 编辑:程序博客网 时间:2024/05/01 15:05

T1 叉叉

题目描述

现在有一个字符串,每个字母出现的次数均为偶数。接下来我们把第一次出现的字母a和第二次出现的a连一条线,第三次出现的和四次出现的字母a连一条线,第五次出现的和六次出现的字母a连一条线...对其他25个字母也做同样3的操作。

现在我们想知道有多少对连线交叉。交叉的定义为一个连线的端点在另外一个连线的内部,另外一个端点在外部。

下图是一个例子,共有三对连线交叉(我们连线的时候,只能从字符串上方经过)。


输入格式

一行一个字符串。保证字符串均由小写字母组成,且每个字母出现次数为偶数次。

输出格式

一个整数,表示答案

样例输入

abaazooabz

样例输出

3

数据范围

对于30%的数据,字符串长度不超过50。

对于100%的数据,字符串长度不超过100,000。

#include#include#include#include#define MAXN 100010using namespace std;char s[MAXN];int nxt[MAXN],cnt[26],pos[26],pre[MAXN];bool is[MAXN];int main(int argc,char *argv[]) {freopen("cross.in","r",stdin);freopen("cross.out","w",stdout);future    scanf("%s",s + 1);    int len = strlen(s + 1);    for(int i=0; i<=25; ++i) pos[i] = len + 1;    memset(nxt,127/3,sizeof nxt );    for(int i=len; i>=1; --i){    ++cnt[s[i] - 'a'];    if(!(cnt[s[i] - 'a'] & 1)) is[i] = true;    nxt[i] = pos[s[i] - 'a'],pos[s[i] - 'a'] = i;}    int Ans = 0;    for(register int i,j=1; j<=26; ++j){    for(i=1; i<=len; ++i)    if(s[i] == 'a' + j - 1) break;    for(int p = i; p<=len; p = nxt[p] ,p = nxt[p])    for(int k=p+1; k<=len && k nxt[p] && is[k]) ++Ans;}}    printf("%d\n",Ans);    fclose(stdin); fclose(stdout);    return 0;}

T2 跳跳虎回家
英文名称: move 时间限制: 1s 空间限制: 256M
题目描述
跳跳虎在外⾯出去玩忘了时间,现在他需要在最短的时间内赶回家。
跳跳虎所在的世界可以抽象成⼀个含有 个点的图(点编号从 到 ),跳跳虎现在在 号点,跳跳虎的家在 号点。
图上⼀共有  条单向边,通过每条边有固定的时间花费。
同时,还存在若⼲个单向传送通道,传送通道也有其时间花费。
传送通道⼀般来说⽐普通的道路更快,但是跳跳虎最多只能使⽤ 次。
跳跳虎想知道他回到家的最⼩时间消耗是多少。
输入格式
第⼀⾏输⼊ 个整数  ( 表⽰点数,  表⽰普通道路的数量, 表⽰传送通道的数量, 表⽰跳跳虎最多使⽤ 次传送通道)
接下来  ⾏每⾏ 个整数  ,表⽰有⼀条从 到 ,时间花费为 的普通道路(  )
接下来 ⾏每⾏ 个整数  ,表⽰有⼀条从 到 ,时间花费为 的传送通道(  )
输出格式
输出⼀⾏⼀个整数表⽰最⼩时间消耗,如果没法回到家输出  。
样例输⼊
5 5 2 1
1 2 1
1 3 2
2 4 2
3 4 3
4 5 4
1 4 1
2 5 1
样例输出
2
数据范围和约定
对于  的数据,
对于另外  的数据,
对于  的数据,
n 1 n 1 n
m
k
4 n,m,q,k n m q k k
m 3 u,v,w u v w 1 ≤ u,v ≤ n,1 ≤ w ≤ 10 3
q 3 x,y,z x y z 1 ≤ x,y ≤ n,1 ≤ z ≤ 10 3
−1
30% 1 ≤ n ≤ 500,0 ≤ m,q ≤ 2000,k = 0
30% 1 ≤ n ≤ 500,0 ≤ m,q ≤ 2000,k = 1
100% 1 ≤ n ≤ 500,0 ≤ m,q ≤ 2000,0 ≤ k ≤ 10^9

#include#include#include#include#include#define MAXN 515#define MAXM 2017using namespace std;struct Edge{ int to,next,value; }e[MAXM << 2];int head[MAXN],dis[MAXN],n,m,q,k,tot;bool exist[MAXN];inline void read(int &x) {    x=0; int f=1; register char c=getchar();    while(c>'9'||c<'0') { if(c=='-')f=-1; c=getchar(); }    while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } x*=f;}inline void Add_Edge(int u,int v,int w) {    e[++tot].to = v,e[tot].value = w,e[tot].next = head[u],head[u] = tot;}int SPFA() {    memset(dis,-1,sizeof dis );    queue q; q.push(1); dis[1] = 0;    while(!q.empty()) {        int u = q.front(); q.pop(); exist[u] = false;        for(int i=head[u]; i; i=e[i].next) {            int v = e[i].to;            if(dis[v] == -1 || dis[v] > dis[u] + e[i].value) {                dis[v] = dis[u] + e[i].value;                if(!exist[v]) q.push(v),exist[v] = true;            }        }    }    return dis[n];}void solve() {    int u,v,w,Ans = 1e9 + 7;    for(register int i=1; i<=m; ++i)        read(u),read(v),read(w),Add_Edge(u,v,w);    ++tot;    for(register int i=1; i<=q; ++i) {        read(u),read(v),read(w);        int temp = head[u];        e[tot].to = v,e[tot].value = w,e[tot].next = head[u],head[u] = tot;        int tmp = SPFA();        if(tmp != -1) Ans = min(tmp,Ans);        head[u] = temp;    }    printf("%d\n",Ans);    fclose(stdin); fclose(stdout);    exit(0);}void xolve() {    int u,w,v;    for(register int i=1; i<=m; ++i)        read(u),read(v),read(w),Add_Edge(u,v,w);    printf("%d\n",SPFA());    fclose(stdin); fclose(stdout);    exit(0);}void caolidie() {    int u,v,w,Ans = 1e9 + 7;    for(register int i=1; i<=m; ++i)        read(u),read(v),read(w),Add_Edge(u,v,w);    for(register int i=1; i<=q; ++i)         read(u),read(v),read(w),Add_Edge(u,v,w);    printf("%d\n",SPFA());    fclose(stdin); fclose(stdout);    exit(0);}int main(int argc,char *argv[]) {freopen("move.in","r",stdin);freopen("move.out","w",stdout);    read(n),read(m),read(q),read(k);    if(k == 0) xolve();    else if(k == 1) solve();    else caolidie();    return 0;}

树(T3的题目原型:51Nod 算法马拉松3 Tree)
System Message (命题人)
基准时间限制:1 秒 空间限制:131072 KB 分值: 80

今天小a在纸上研究树的形态,众所周知的,有芭蕉树,樟树,函树,平衡树,树套树等等。那么小a今天在研究的就是其中的平衡树啦。

小a认为一棵平衡树的定义为一个n个点,从1到n编号,n-1条边,且任意两点间一定存在唯一一条简单路径,且n>=k。

现在小a看到一棵很大很大的树,足足有n个节点,这里n一定大于等于k!为了方便起见,它想把这个树删去某些边,使得剩下的若干个联通块都满足是平衡树。这时,小b走过来,不屑一顾的说,如果我一条边都不删,那么也算一棵平衡树咯。

小a对于小b的不屑感到很不爽,并问小b,你能算出我删边的方案总数使得满足我的条件吗?两个删边的方案A,B不同当且仅当存在某一条边属于集合A且不属于集合B,或者存在某一条边属于集合B且不属于集合A。为了让你方便,你只要告诉我答案对1000000007(1e9+7)取模就行了。

小b犯了难,找到了身为程序猿的你。

Hint:

样例解释,

第一种方案为不删边,

第二种方案为删去2 3这一条边,

第三种方案为删去3 4这一条边。


分析:我们令dp[i][j]表示以i为根且当前联通块大小为k的方案总数,特别的,dp[i][0]表示割点当前点与其父亲是棵平衡树的方案总数。

对于u的一个孩子v可以得到转移方程dp[u][j+k]=dp[u][j]*dp[v][k]

另外dp[u][0]=Σdp[u][j](j>=题目给定的k)

这样乍看是n^3的,有一个技巧可以做到n^2即每次dp时,只枚举当前u所在子树的大小,每当枚举到它的其中孩子时,当前u所在子树的大小加上它孩子为根的子树的大小。可以理解为每一个点对只被枚举到一次。

最后答案即为dp[root][0]

#include#include#include#include#define MAXN 2222#define Mod 1000000007using namespace std;typedef long long LL;int n,K,tot,head[MAXN],siz[MAXN];LL dp[MAXN][MAXN];struct Edge { int to,next; }e[MAXN << 1];inline void Add_Edge(int u,int v) {    e[++tot].to = v,e[tot].next = head[u],head[u] = tot;    e[++tot].to = u,e[tot].next = head[v],head[v] = tot;}inline void ADD_MOD(LL &x,LL y) {    x += y;    if(x >= Mod) x -= Mod;}inline void read(int &x) {    x = 0; register char c = getchar();    while(c > '9' || c < '0') c = getchar();    while(c >= '0' && c<= '9') { x = x * 10 + c - '0'; c = getchar(); }}void DFS(int u,int fa) {    siz[u] = 1,dp[u][ siz[u] ] = 1;    for(int i=head[u]; i; i=e[i].next) {        int v = e[i].to;        if(v == fa) continue;        DFS(v,u);        for(int j=siz[u]; j>=1; --j){            for(int k=siz[e[i].to]; k>=1; --k)                 ADD_MOD(dp[u][j + k],(LL)dp[u][j] * dp[e[i].to][k] % Mod);            dp[u][j] = (LL)dp[u][j] * dp[e[i].to][0] % Mod;        }        siz[u] += siz[e[i].to];    }    for(int k=K; k<=siz[u]; ++k) ADD_MOD(dp[u][0],dp[u][k]);}int main(int argc,char *argv[]) {    read(n),read(K);    int u,v;    for(register int i=1; i<=n-1; ++i)        read(u),read(v),Add_Edge(u,v);    DFS(1,-1);    printf("%d\n",dp[1][0]);    return 0;}

阅读全文
0 0
原创粉丝点击