2018沈阳集训day1

问题 A: 马克的字符串

时间限制: 1 Sec  内存限制: 256 MB

题目描述

定义一个字符串满足'MK'性质当且仅当它修改其中不超过k个字符后是回文串。给你一个字符串,问它有多少非空子串满足'MK'性质。

输入

输入的第一行包含一个字符串s

输入的第二行包含一个整数k

输出

输出的第一行包含一个整数,为满足'MK'性质的字串数量。

样例输入

Aab
1

样例输出

6

提示

【样例说明】

 

每一个字串都是回文串或修改一个字母后是回文串

 

【数据规模与约定】

 

对于30%的数据:k=0


对于100% 的数据:字符串长度 1<=l<=100,0<=k<=50

题解:n^3暴力,开始跑了个manacher,结果WA了,至今迷

#include<bits/stdc++.h>
using namespace std;
char str[208];
int k; 
bool check(int i, int j){
    int cnt = 0;
    while(i <= j){
        if(str[i]  != str[j])cnt ++;
        if(cnt > k)return 0;
        i++, j--;
    }
    return 1;
}
int main(){
    scanf("%s", str);
    scanf("%d", &k);
    int ans = 0;
    int len = strlen(str); 
    for(int i = 0; i < len; i++)
        for(int j = i; j < len; j++)
            ans += check(i, j); 
    printf("%d",ans);
}
View Code

 

问题 B: 马克家的书

时间限制: 1 Sec  内存限制: 256 MB

题目描述

马克家收藏了一套书,这套书叫《OIER故事集》,这套书有n本,每本书有一个编号,从1号到n号。

马克把这些书按照编号从小到大,从上往下摞成一摞。马克对这套书很珍视,不允许其他人动。

有一天一格到马克家玩,马克因为和妹子约会,就让一格自己呆在家里。一格因为对这套书非常好奇,偷偷的看了一下,结果发现书中竟然有ljscommonc的故事。一格看的入了迷,结果把一摞书的顺序弄乱了。

眼看着马克就要回来了,一格需要把书恢复到原状,由于每本书都比较重,所以一格能做的操作是把一本书从书堆中抽出来,然后把这本书放到书堆的顶部。

给你打乱的书的顺序,你能帮一格算算最少需要几次上述操作,才能恢复书的顺序。

输入

第一行包含一格正整数T(T<=10),表示数据组数。

对于每组数据,第一行为一格整数n

接下来的一行有n个用空格分开的正整数,表示一格打乱后的书的顺序,从上到下。

输出

对于每组数据,输出一行一个整数,表示一格最少经过几次操作才能恢复书的顺序

样例输入

2
4
4 1 2 3
5
1 2 3 4 5

样例输出

3
0

提示

【样例说明】

 

对于第一组数据,我们先把3号书放在最上面,接着操作2号书,最后操作1号书,(4123)—(3412)—(2341)—(1234)这样就有序了

 

对于第二组数据,已经有序就不需要挪了。

 

【数据规模与约定】

 

对于 50% 的数据满足 n<=10

 

对于 80%的数据满足 n<=1000


对于 100% 的数据满足 n<=100000

  题解:智力题,从后往前扫,递减序列,其他的最少移动一次

 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
int a[maxn];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        int p = n, cnt = 0;
        for(int i = n; i >= 1; i--)
            if(a[i] == p)p--, cnt++;
        printf("%d\n",n - cnt);
    }
     
}
View Code

 

 

 

 

问题 C: 马克的幸运数

时间限制: 1 Sec  内存限制: 256 MB

 

题目描述

 

马克和同学们玩卡牌游戏。一共有n张卡牌,每张卡牌上有一个数Ai,每次可以从中选出k张卡牌。一种选取方案的幸运数为这k张卡牌上数的异或和。马克想知道所有选取方案的幸运数之和除以998244353的余数。

 

输入

 

第一行有两个整数n和k。

第二行有n个整数,表示序列A。

 

输出

 

一行,一个整数,表示答案。

 

样例输入

 

3 2
1 2 3

 

样例输出

 

6

 

提示

 

【样例说明】

 

样例1幸运值之和为(1 ⊕ 2) + (1 ⊕ 3) + (2 ⊕ 3) = 6

 

 


【样例输入2】


10 5


123 456 789 987 654 321 101 202 303 404


【样例输出2】


130776


 


【数据规模与约定】


对于30%的数据满足,1<=n<=20


对于另30%的数据满足,1<=n<=100,0<Ai<=1024


对于80%的数据满足,1<=n<=2000


对于100%的数据满足,1<=n<=100000,0<Ai<2^31,1<=k<=n

 题解:亦或和拆位,统计每位有1的个数,只有选奇数个才有贡献,然后方枚举选1多少个,选0多少个,乘法原理,注意特判不要超过k

 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
#define ll long long
ll a[maxn], fac[maxn], infac[maxn];
const ll p = 998244353;
ll exgcd(ll a, ll b, ll &x, ll &y){
    if(b == 0){
        x = 1; y = 0; return a;
    }
    ll x0, y0;
    ll d = exgcd(b, a % b, x0, y0);
    x = y0;
    y = x0 - (a / b ) * y0; 
    return d;
}
ll inv(ll a){
    ll x, y;
    exgcd(a, p, x, y);
    return (x % p + p) % p;
}
int main(){
    int n, k;
    fac[0] = 1;
    infac[0]= 1;
    ll ans = 0;
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++){
        scanf("%lld", &a[i]);
        fac[i] = fac[i-1] * i % p;
        infac[i] = inv(fac[i]);
    }
    long long an=1;
    for(int i = 0; i <= 31; i++){
        int sum = 0;
        for(int j = 1; j <= n; j++)
            if(a[j] & (1<<i) )sum++;  
        int siz = min(k, sum);
        for(int j = 1; j <= siz; j+=2)
            if (k - j <= n-sum )
                ans = ( ans +  ( (1ll<<i) % p * (fac[sum] * infac[j] % p * infac[sum-j] % p ) % p * (fac[n - sum] * infac[n - sum - k + j] % p * infac[k - j] % p) ) )% p;
    }
    printf("%lld\n", ans);
}
View Code

 

 

 

 

问题 D: 马克的达人秀

时间限制: 1 Sec  内存限制: 256 MB

 

题目描述

 

马克要带着他的N个oier,方便起见编号为1…N,到oi展览会上去,参加每年的达人秀!他的第i个oier体重为wi,才艺水平为ti,两者都是整数。在到达时,马克就被今年达人秀的新规则吓到了:

(一)参加比赛的一组oier必须总重量至少为W(这是为了确保是强大的队伍在比赛,而不仅是强大的某个oier),并且

(二)总才艺值与总重量的比值最大的一组获得胜利。

马克注意到他的所有oier的总重量不小于W,所以他能够派出符合规则(一)的队伍。帮助他确定这样的队伍中能够达到的最佳的才艺与重量的比值。

 

输入

 

输入的第一行包含N和W。下面N行,每行用两个整数wi和ti描述了一个oier。

 

输出

 

请求出马克用一组总重量最少为W的oier最大可能达到的总才艺值与总重量的比值。

如果你的答案是A,输出1000*A向下取整的值,以使得输出是整数

(当问题中的数不是一个整数的时候,向下取整操作在向下舍入到整数的时候去除所有小数部分)。

 

样例输入

 

3 15
20 21
10 11
30 31

 

样例输出

 

1066

 

提示

 

在这个例子中,总体来看最佳的才艺与重量的比值应该是仅用一个才艺值为11、重量为10的oier,但是由于我们需要至少15单位的重量,最优解最终为使用这头奶牛加上才艺值为21、重量为20的oier。这样的话才艺与重量的比值为(11+21)/(10+20)=32/30=1.0666666…,乘以1000向下取整之后得到1066。

 

【数据规模与约定】


对于20%的数据满足,1<=n<=20


对于40%的数据满足,1<=n<=50,输出答案保证小于23333


对于100%的数据满足,1≤N≤250,1≤W≤1000,1≤wi≤10^6,1≤ti≤10^3


保证数据有梯度

 题解:dp,01背包, f[i][j]表示达到才艺值为i最少花的体力, 答案就在dp[0~sum][w] (w >W)中

#include<bits/stdc++.h>
using namespace std;
const int maxn = 300, maxm = 300005, inf = 1000000008;
int N, W;
const double eps = 1e-6;
struct cow{
    int t, w; double val;
}c[maxn];
int dp[2][maxm];
int main(){
    scanf("%d%d", &N, &W);
    int sum = 0; double ans = 0;
    for(int i = 1; i <= N; i++)
        scanf("%d%d", &c[i].w, &c[i].t), sum += c[i].t;
    int u = 0;
    for(int i = 1; i <= sum; i++) dp[u][i] = inf;
    dp[0][0] = 0;
    for(int i = 1; i <= N; i++){
        u ^= 1;
        for(int j = 0; j <= sum; j++)dp[u][j] = dp[u^1][j];
        for(int j = c[i].t; j <= sum; j++)dp[u][j] = min(dp[u][j], dp[u^1][j - c[i].t] + c[i].w);
        /*for(int j = 0; j <= sum; j++)if(dp[u][j] != inf){
            printf("i = %d j = %d dp = %d\n",i,j,dp[u][j]);
        }*/
    }
    for(int i = 0; i <= sum; i++)
        if(dp[u][i] >= W) ans = max(ans, 1.0 * i / dp[u][i]);
    printf("%d\n", (int) floor(ans*1000));
}
View Code

 

 

 

第一天考崩了,差距巨大,后面怎么也追不上去,奠定我在联训悲惨的基调

posted @ 2018-06-14 08:04  Ed_Sheeran  阅读(820)  评论(1编辑  收藏  举报