问题 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