求调刚才T1
  • 板块学术版
  • 楼主Night_sea_64
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/11/9 13:11
  • 上次更新2024/11/9 15:24:52
查看原帖
求调刚才T1
554145
Night_sea_64楼主2024/11/9 13:11

60pts

思路是二分查找每个位置跳一次后的位置,然后倍增

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int mod=1e9+7;
int n,m,q,a[400010],s[400010];
int d1[200010][65],d2[200010][65];
signed main()
{
    // freopen("kingdom5.in","r",stdin);
    // freopen("kingdom.out","w",stdout);
    scanf("%lld%lld%lld",&n,&m,&q);
    for(int i=1;i<=n;i++)
    {
        char c;
        cin>>c;
        a[i]=c-'0';
        s[i]=s[i-1]+a[i];
    }
    for(int i=n+1;i<=2*n;i++)
        a[i]=a[i-n],s[i]=s[i-1]+a[i];
    for(int i=1;i<=n;i++)
        if(m<n)
        {
            if(s[i+m]==s[i])d1[i][0]=d2[i][0]=1;
            else
            {
                int l=i+1,r=i+m,pos;
                while(l<=r)
                {
                    int mid=(l+r)/2;
                    if(s[mid]==s[i+m])r=mid-1,pos=mid;
                    else l=mid+1;
                }
                d1[i][0]=d2[i][0]=pos-i;
            }
        }
        else
        {
            if(s[n]==0)d1[i][0]=1%n,d2[i][0]=1;
            else
            {
                int l=i+1,r=i+m%n,pos;
                while(l<=r)
                {
                    int mid=(l+r)/2;
                    if(s[mid]==s[i+m%n])r=mid-1,pos=mid;
                    else l=mid+1;
                }
                d1[i][0]=(m-(i+m%n-pos))%n,d2[i][0]=(m-(i+m%n-pos))%mod;
            }
        }
    for(int j=1;j<=60;j++)
        for(int i=1;i<=n;i++)
        {
            int nxt=(i+d1[i][j-1]-1)%n+1;
            d1[i][j]=(d1[i][j-1]+d1[nxt][j-1])%n;
            //if(i==7&&j==1)cout<<d1[i][j]<<endl;
            //if(i==1&&j==2)cout<<nxt<<" "<<d1[i][j-1]<<" "<<d1[nxt][j-1]<<" "<<d1[i][j]<<endl;
            d2[i][j]=(d2[i][j-1]+d2[nxt][j-1])%mod;
        }
    /*for(int j=0;j<=3;j++)
    {
        for(int i=1;i<=n;i++)
            cout<<d1[i][j]<<" ";
        cout<<endl;
    }cout<<endl;
    for(int j=0;j<=3;j++)
    {
        for(int i=1;i<=n;i++)
            cout<<d2[i][j]<<" ";
        cout<<endl;
    }*/
    while(q--)
    {
        int s,k;
        scanf("%lld%lld",&s,&k);
        int now=(s-1)%n+1,ans=s%mod;
        for(int i=60;i>=0;i--)
            if(k>=(1ll<<i))
            {
                k-=(1ll<<i);
                ans=(ans+d2[now][i])%mod;
                now=(now+d1[now][i]-1)%n+1;
                //cout<<i<<" "<<now<<" "<<ans<<endl;
            }
        printf("%lld\n",ans);
    }
    return 0;
}
2024/11/9 13:11
加载中...