目录
1275 最大数
给定一个正整数数列 a1,a2,…,an,每一个数都在 0∼p−1 之间。
可以对这列数进行两种操作:
- 添加操作:向序列后添加一个数,序列长度变成 n+1;
- 询问操作:询问这个序列中最后 L 个数中最大的数是多少。
程序运行的最开始,整数序列为空。
一共要对整数序列进行 m 次操作。
写一个程序,读入操作的序列,并输出询问操作的答案。
输入格式
第一行有两个正整数 m,p,意义如题目描述;
接下来 m 行,每一行表示一个操作。
如果该行的内容是 Q L
,则表示这个操作是询问序列中最后 L 个数的最大数是多少;
如果是 A t
,则表示向序列后面加一个数,加入的数是 (t+a) mod p。其中,t 是输入的参数,a 是在这个添加操作之前最后一个询问操作的答案(如果之前没有询问操作,则 a=0)。
第一个操作一定是添加操作。对于询问操作,L> 且不超过当前序列的长度。
输出格式
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后 L 个数的最大数。
数据范围
1≤m≤2×105,
1≤p≤2×109
0≤t<p
输入样例:
10 100
A 97
Q 1
Q 1
A 17
Q 2
A 63
Q 1
Q 1
Q 3
A 99
输出样例:
97
97
97
60
60
97
样例解释
最后的序列是 97,14,60,9697,14,60,96。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 2e5+10;
typedef long long ll;//会爆int
struct xds{
int l,r;ll v;
}tr[4*N];//开四倍大小
int m,p,n,last;
inline void build(int u,int l,int r){
tr[u]={l,r};
if(l==r)return;
int mid(l+r>>1);
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
inline void pushup(int u){
tr[u].v=max(tr[u<<1].v,tr[u<<1|1].v);//pushup操作
}
inline ll query(int u,int l,int r){
if(l<=tr[u].l&&r>=tr[u].r)return tr[u].v;
int mid=tr[u].l+tr[u].r>>1;
ll v(0);
if(l<=mid)v=max(v,query(u<<1,l,r));//左边找最大值
if(r>mid)v=max(v,query(u<<1|1,l,r));//右边找最大值
return v;
}
inline void modify(int u,int x,ll v){
if(tr[u].l==x&&tr[u].r==x)tr[u].v=v;//找到就添加
else {
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid)modify(u<<1,x,v);//在左子树
else modify(u<<1|1,x,v);//在右子树
pushup(u);//pushup操作,更新父节点最大值
}
}
int main(){
scanf("%d%d",&m,&p);
build(1,1,m);
while(m--){
char op[2];
ll x;
scanf("%s %lld",op,&x);
if(*op=='Q'){
last=query(1,n-x+1,n);//查询n-x+1~n最大值
printf("%d\n",last);
}
else {
modify(1,n+1,(x+last)%p);//添加数
n++;
}
}
}
1303 斐波那契前n项和
大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2 |
现在问题很简单,输入 n 和 m,求 fn的前 n 项和 Sn mod m
输入格式
共一行,包含两个整数 n 和 m。
输出格式
输出前 n 项和 Sn mod m 的值。
数据范围
1≤n≤2000000000
1≤m≤1000000010
输入样例:
5 1000
输出样例:
12
#include<bits/stdc++.h>
using namespace std;
int n,m;
typedef long long LL;
void mul(int c[],int a[],int b[][3])
{
int t[3]={0};
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
t[i]=(t[i]+(LL)a[j]*b[j][i])%m;
}
}
memcpy(c,t,sizeof t);
}
void mul(int c[][3],int a[][3],int b[][3])
{
int t[3][3]={0};
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
for(int k=0;k<3;k++){
t[i][j]=(t[i][j]+(LL)a[i][k]*b[k][j])%m;
}
}
}
memcpy(c,t,sizeof t);
}
int main()
{
cin>>n>>m;
int f[3]={1,1,1};
int a[3][3]={
{0,1,0},
{1,1,1},
{0,0,1}
};
n--;
while(n)
{
if(n&1)mul(f,f,a);
mul(a,a,a);
n>>=1;
}
cout<<f[2];
return 0;
}
1304 佳佳的斐波那契
佳佳对数学,尤其对数列十分感兴趣。
在研究完 Fibonacci 数列后,他创造出许多稀奇古怪的数列。
例如用 S(n) 表示 Fibonacci 前 n 项和 mod m 的值,即 S(n)=(F1+F2+…+Fn ) mod m,其中 F1=F2=1,Fi=Fi−1+Fi−2
可这对佳佳来说还是小菜一碟。
终于,她找到了一个自己解决不了的问题。
用 T(n)=(F1+2F2+3F3+…+nFn) mod m表示 Fibonacci 数列前 n 项变形后的和 mod m 的值。
现在佳佳告诉你了一个 n 和 m,请求出 T(n) 的值。
输入格式
共一行,包含两个整数 n 和 m。
输出格式
共一行,输出 T(n) 的值。
数据范围
1≤n,m≤231−1
输入样例:
5 5
输出样例:
1
样例解释
T(5)=(1+2×1+3×2+4×3+5×5)mod5=1
#include<bits/stdc++.h>
using namespace std;
int n,m;
typedef long long LL;
void mul(int c[][4],int a[][4],int b[][4])
{
int t[4][4]={0};
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
for(int k=0;k<4;k++){
t[i][j]=(t[i][j]+(LL)a[i][k]*b[k][j])%m;
}
}
}
memcpy(c,t,sizeof t);
}
int main()
{
cin>>n>>m;
int k=n-1;
int f[4][4]={1,1,1,0};
int a[4][4]={
{0,1,0,0},
{1,1,1,0},
{0,0,1,1},
{0,0,0,1}
};
while(k)
{
if(k&1)mul(f,f,a);
mul(a,a,a);
k>>=1;
}
cout<<(((LL)n*f[0][2]-f[0][3])%m+m)%m;
return 0;
}
1292 哥德巴赫猜想
哥德巴赫猜想的内容如下:
任意一个大于 44 的偶数都可以拆成两个奇素数之和。
例如:
8=3+5
20=3+17=7+13
42=5+37=11+31=13+29=19+23
现在,你的任务是验证所有小于一百万的偶数能否满足哥德巴赫猜想。
输入格式
输入包含多组数据。
每组数据占一行,包含一个偶数 n。
读入以 0 结束。
输出格式
对于每组数据,输出形如 n = a + b
,其中 a,b是奇素数。
若有多组满足条件的 a,b,输出 b−a 最大的一组。
若无解,输出 Goldbach's conjecture is wrong.
。
数据范围
6≤n<106
输入样例:
8
20
42
0
输出样例:
8 = 3 + 5
20 = 3 + 17
42 = 5 + 37
#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
int p[N],cnt;
bool st[N];
void get()
{
for(int i=2;i<=1000000;i++){
if(!st[i])p[cnt++]=i;
for(int j=0;p[j]*i<=1000000;j++){
st[p[j]*i]=true;
if(i%p[j]==0)break;
}
}
}
int main()
{
get();
int n;
while(cin>>n,n)
{
bool flag=true;
for(int i=1;i<cnt;i++){
if(!st[n-p[i]]){
flag=false;
printf("%d = %d + %d\n",n,p[i],n-p[i]);
break;
}
}
if(flag)puts("Goldbach's conjecture is wrong.");
}
return 0;
}
1293 夏洛克和他的女朋友
夏洛克有了一个新女友(这太不像他了!)。
情人节到了,他想送给女友一些珠宝当做礼物。
他买了 n 件珠宝,第 i 件的价值是 i+1,也就是说,珠宝的价值分别为 2,3,…,n+1
华生挑战夏洛克,让他给这些珠宝染色,使得一件珠宝的价格是另一件珠宝的价格的质因子时,两件珠宝的颜色不同。
并且,华生要求他使用的颜色数尽可能少。
请帮助夏洛克完成这个简单的任务。
输入格式
只有一行一个整数 n,表示珠宝件数。
输出格式
第一行一个整数 k,表示所使用的颜色数;
第二行 n 个整数,表示第 1 到第 n 件珠宝被染成的颜色。
若有多种答案,输出任意一种。
请用 1 到 k 表示你用到的颜色。
数据范围
1≤n≤105
输入样例1:
3
输出样例1:
2
1 1 2
输入样例2:
4
输出样例2:
2
2 1 1 2
#include<bits/stdc++.h>
using namespace std;
int p[100010],cnt;
bool st[100010];
void get()
{
for(int i=2;i<=100001;i++){
if(!st[i])p[cnt++]=i;
for(int j=0;p[j]*i<=100001;j++){
st[p[j]*i]=true;
if(i%p[j]==0)break;
}
}
}
int main()
{
get();
int n;
cin>>n;
if(n<=2)puts("1");
else puts("2");
for(int i=2;i<=n+1;i++){
if(!st[i])cout<<1<<" ";
else cout<<2<<" ";
}
return 0;
}
1289 序列的第k个数
BSNY 在学等差数列和等比数列,当已知前三项时,就可以知道是等差数列还是等比数列。
现在给你 整数 序列的前三项,这个序列要么是等差序列,要么是等比序列,你能求出第 k 项的值吗。
如果第 k 项的值太大,对其取模 200907。
输入格式
第一行一个整数 T,表示有 T组测试数据;
对于每组测试数据,输入前三项 a,b,c,然后输入 k。
输出格式
对于每组数据,输出第 k 项取模 200907 的值。
数据范围
1≤T≤100
1≤a≤b≤c≤109
1≤k≤109
输入样例:
2
1 2 3 5
1 2 4 5
输出样例:
5
16
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod=200907;
int qmi(int a,int k)
{
int res=1;
while(k)
{
if(k&1)res=(LL)res*a%mod;
a=(LL)a*a%mod;
k>>=1;
}
return res;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int a,b,c,k;
cin>>a>>b>>c>>k;
if(a+c==2*b)cout<<(a+(b-a)*(LL)(k-1))%mod<<endl;
else cout<<(LL)a*qmi(b/a,k-1)%mod<<endl;
}
return 0;
}
1290 越狱
监狱有连续编号为 1 到 n 的 n 个房间,每个房间关押一个犯人。
有 m 种宗教,每个犯人可能信仰其中一种。
如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。
求有多少种状态可能发生越狱。
输入格式
共一行,包含两个整数 m 和 n。
输出格式
可能越狱的状态数,对 100003 取余。
数据范围
1≤m≤108
1≤n≤1012
输入样例:
2 3
输出样例:
6
样例解释
所有可能的 66 种状态为:(000)(001)(011)(100)(110)(111)
#include<bits/stdc++.h>
using namespace std;
const int mod=100003;
typedef long long LL;
LL qmi(LL a,LL k)
{
LL res=1;
while(k)
{
if(k&1)res=res*a%mod;
a=a*a%mod;
k>>=1;
}
return res;
}
int main()
{
LL m,n;
cin>>m>>n;
cout<<(qmi(m,n)-m*qmi(m-1,n-1)%mod+mod)%mod;
return 0;
}