acwing 刷题

13 篇文章 0 订阅

目录

1275 最大数

1303 斐波那契前n项和

1304 佳佳的斐波那契

1292 哥德巴赫猜想

 1293 夏洛克和他的女朋友

1289 序列的第k个数

 1290 越狱


1275 最大数

给定一个正整数数列 a1,a2,…,an,每一个数都在 0∼p−1 之间。

可以对这列数进行两种操作:

  1. 添加操作:向序列后添加一个数,序列长度变成 n+1;
  2. 询问操作:询问这个序列中最后 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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值