天梯赛校内选拔

问题 A: [30分]数列求值
f(1) = 1,f(2) = 1,求f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7。

裸的矩阵快速幂

#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
#define N 4
#define mod 7
using namespace std;
struct Mtx{
    LL a[N][N];
}m;
const int n=2;
int a,b,p;
void init(){
    m.a[1][1]=a;
    m.a[1][2]=b;
    m.a[2][1]=1;
    m.a[2][2]=0;
}
Mtx Mul(Mtx x,Mtx y){
    Mtx ans;
    memset(&ans,0,sizeof ans);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            for(int k = 1; k <= n ; ++k)
                ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
    return ans;
}
Mtx pow(Mtx x,LL p){
    Mtx ans = m;
    while(p)
    {
        if(p&1) ans = Mul(ans,x);
        x = Mul(x,x);
        p>>=1;
    }
    return ans;
}
void solve(int k){
    Mtx am = m;
    if (k>3) am = pow(m,k-3);
    int res = (am.a[1][1] + am.a[1][2])%7;
    printf("%d\n",res);
    /*
    for (int i=1;i<=2;i++) 
    {
        cout << am.a[i][1]<< ' '<<am.a[i][2]<<endl;
    }
    */
}
int main(){
    while(cin >> a >> b >>p)
    {
        init();
        if(p==1 || p==2) printf("1\n");
        else {
            solve(p);
        }
    }
    return 0;
}
/**************************************************************
    Problem: 2231
    User: team50
    Language: C++
    Result: 正确
    Time:0 ms
    Memory:1700 kb
****************************************************************/

问题 N: [15分]老王的春天
时间限制: 2 Sec 内存限制: 128 MB
提交: 170 解决: 31
题目描述

老王今天心情很好,准备出去溜达溜达,万一隔壁就有大收获呢~

然而高度近视的他今天忘记戴眼镜,以至于看不清路面,经常撞头,他在一个一维坐标系上走动,有些坐标存在石头(一个坐标可以有多个石头)。 当前方有石头时,老王会撞掉石头,目标坐标的石头数减1,并维持原坐标;当前方没有石头时,老王会往前一步走。 根据给定的方向,模拟撞头以及步行,求出最后的坐标。坐标范围是[-10000,+10000]。

输入

第1行为一个整数T(1<=T<=100),代表测试数据个数;
接下来有T组数据: 
	每组数据第1行为一个整数n(1<=n<=1000),代表石头个数
接下来一行有n个整数,代表石头坐标,注意可以重复的噢,一个坐标可以有多个石头,每次碰到会撞掉一个石头
接下来一行输入一个整数,代表老王的初始坐标
最后一行由"<->,"四个字符构成的字符串,记录了老王的行动轨迹

输出

如果给定的轨迹字符串正确,则输出最终坐标,否则输出Boom!

样例输入

3
5
3 3 5 6 7
4
<-,->
5
3 3 5 6 7
4
<-,<-,->,=>,->
5
3 3 5 6 7
4
<-,<-,->,->,->,->

样例输出

Case 1:4
Case 2:Boom!
Case 3:6

模拟:我一开始想下标为负数的数组不是pascal里才有吗。
就在我还在想c++有没有这样的特性的时候,突然一拍大腿!开两个数组不就行了!

#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long 
#define INF 2147483647
#define N 10010
using namespace std;
int t,n,pos1[N],pos2[N],cmd[N],sum,p0;
int flag;
inline void init(){
    flag=0;
    memset(pos1,0,sizeof pos1);
    memset(pos2,0,sizeof pos2);
    scanf("%d",&n);
    int p;
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&p);
        if (p>=0) pos1[p]++;
        else pos2[-p]++; 
    }
    scanf("%d",&p0);
    char str[4*N];  
    scanf("%s",str);
    int len = strlen(str);
    for (int i=0;i<len;i++)
    {
        if (str[i]=='<' || str[i]=='>'||str[i]==',' ||str[i]=='-') continue;
        flag=1;
    }
    sum=(len+1)/3;
    for (int i=1;i<=sum;i++) 
    {
        int pos=3*i-1;
        if (str[pos-1]=='>') cmd[i]=1;
        else cmd[i]=-1;
    }
     
}
inline void solve(){
    int p = p0;
    for (int i=1;i<=sum;i++)
    {
        if (p+cmd[i]>=0) 
        {
            if (pos1[p+cmd[i]]) 
                pos1[p+cmd[i]]--;
            else p+=cmd[i]; 
        }
        else
        {
            if (pos2[-(p+cmd[i])]) 
                pos2[-(p+cmd[i])]--;
            else p+=cmd[i]; 
        }
    }
    printf("%d\n",p);
}
int main(){
    cin >> t;
    for (int i=1;i<=t;i++)
    {
        init();
        printf("Case %d:",i);
        if (flag) printf("Boom!\n");
        else solve();
    }
    return 0;
} 
/**************************************************************
    Problem: 2244
    User: team50
    Language: C++
    Result: 正确
    Time:340 ms
    Memory:1816 kb
****************************************************************/

问题 M: [25分]你的名字

时间限制: 3 Sec 内存限制: 128 MB
提交: 28 解决: 8
[提交][状态][讨论版]
题目描述

我们知道,一个人有很多的外号名字,例如"姜丽雯"、“lw聚聚”、“姜芋”、“港叔”、“大床龙” 、“小港”、“女装ljy”、“小彬彬”、“张短彬”、"小蒋蒋"等等。 由于有太多的外号,一时半会反应不过来,现在我通过一个列表告诉你,X名字等价于Y名字,A名字等价于B名字,如果Y名字等价于A名字,那么X名字将等价于B名字,以此类推。

现在给你两串字符串,每一串由2个名字连在一起,没有任何分隔,丝滑连接。现在问你,这两串字符串有没有可能是相同的两个人? 很好,你已经知道这个问题考察什么了,这个问题太简单了!姜丽文2秒就搞定了!你呢?
输入

第1行为一个整数T(1<=T<=100),代表测试数据个数;

接下来有T组数据:

每组数据第1行为一个整数n(1<=n<=2000),代表等价名字对数,

接下来n行,每行包括两个字符串a,b(1<=len(a),len(b)<=100),代表名字a和b是等价的

接下来2行是两个字符串x,y(2<=len(x),len(y)<=200),分别代表2个名字连在一起
输出

如果名字串x的两个名字和名字串y的两个名字是代表相同的两个人,输出"Yes",否则输出"No"
样例输入

2
3
jiangliwen lwjuju
lwjuju hongtaiyang
wanghaogang gangshu
wanghaogangjiangliwen
gangshuhongtaiyang
2
jiangliwen lwjuju
zhangchangbing zhangduanbing
jiangliwenzhangduanbing
lwjujuzhangchangbing
样例输出

Case 1:Yes
Case 2:Yes
提示

1.暴力找分割点(有人叫陈俊,也可以有人叫陈俊宇啊)

2.注意只要两个名字是相同的两个人即可,即便顺序不一样

并查集+暴力

问题 L: [20分]首尾排序法

时间限制: 1 Sec 内存限制: 128 MB
提交: 69 解决: 4

题目描述

有一个长度为n的数组 p1, p2, p3, ⋯, pn ,且每个数字都不一样。现在要对这个数组进行从小到大排序,排序的时候只能是把一个数字拿过来放到数组末尾或者开头,问最少要操作几次才能使得这个数组从小到大排序。
输入

单组测试数据。
第一行一个整数n (1≤n≤100000),表示数组的长度。
第二行有n个整数 pi (-1e7≤pi≤1e7, 如果 i≠j,那么pi≠pj ) ,表示数组中的数字。
输出

输出一个整数,表示最少要操作几次才能使得数组从小到大有序。
样例输入

5
4 1 2 5 3
样例输出

2

51nod 1700

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值