zjnu1730 PIRAMIDA(字符串,模拟)

Description

Sample Input

     
     
6 JANJETINA 5 1 J 1 A 6 N 6 I 5 E

Sample Output

     
     
1 0 2 1 1

题意:给你一个长度小于等于10^6的字符串,然后每次让它循环铺盖,构成层数为n的塔,让你求得第i层塔中某个字符的个数。

思路:首先要注意到字符串是从左到右覆盖该行和从右到做覆盖该行不影响结果,所以我们全部考虑为从左到右覆盖。我们先遍历一遍字符串,用vector<int>vect[30]记录字符为i的所有位置。然后我们看c是不是能被字符串的长度len整除,如果能,那么答案就是vec[c-'A'+1].size()*c/len,如果不能整除,那么我们就要把余下的部分算完。当我们把中间的整段字符串都去掉的时候,余下的部分可能是前面一串,或者后面一串,或者前面后面都有剩下的,这里一开始我直接算前一串的开头到len-1中的数量加上后一串的0到结尾的数量,但是wa了,因为这样的想法是错误的。因为我这样算可能会包含已经算过的,比如abcdefabcdef,如果我选第2个b和倒数第2个e,那么我这样算的话,会包含之前算过的,因为两个字符间的距离大于len了。所以我们要采用别的方法,起始点q固定,尾节点变为(q+(c%len))%len,那么起始点和尾节点之间的距离一定小于len了,这样就不会重复算了。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 1000050
vector<int>vec[30];
vector<int>::iterator it;
int len;
int chuli(int pos,int bianhao)
{
    int i,j;
    int p;
    p=upper_bound(vec[bianhao].begin(),vec[bianhao].end(),pos)-vec[bianhao].begin();
    return p;
}
int getkaitou(ll ceng)
{
    int i,j;
    ll sum;
    if(ceng==1)return 0;
    if(ceng%2==0)sum=( (ceng/2%len)*((ceng-1)%len)+1 )%len;
    else sum=( (ceng%len)*((ceng-1)/2%len)+1 )%len;
    if(sum==0)sum=len-1;
    else sum--;
    return sum;
}
char s[maxn];

int main()
{
    int m,i,j;
    ll n,c;
    while(scanf("%lld",&n)!=EOF)
    {
        scanf("%s",s);
        len=strlen(s);
        for(i=1;i<=26;i++)vec[i].clear();

        for(i=0;i<len;i++){
            vec[s[i]-'A'+1].push_back(i);
        }
        char str[10];
        int p;
        ll sum;
        scanf("%d",&m);
        while(m--){
            scanf("%lld%s",&c,str);
            int bianhao=str[0]-'A'+1;
            int kaitou=getkaitou(c);
            if(c%len==0){
                printf("%lld\n",(ll)vec[bianhao].size()*(ll)(c/len) );
                continue;
            }
            ll beishu=c/len;
            sum=0;
            sum+=(ll)beishu*(ll)vec[bianhao].size();
            ll jianju=c%len;
            int jiewei=(kaitou+jianju-1)%len;
            if(kaitou<=jiewei){
                printf("%lld\n",sum+chuli(jiewei,bianhao)-chuli(kaitou-1,bianhao)  );
            }
            else{
                printf("%lld\n",sum+chuli(jiewei,bianhao)+chuli(len-1,bianhao)-chuli(kaitou-1,bianhao) );
            }
        }
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值