洛谷 U28036 Nagisa loves Tomoya(推式子) 题解

题目来源:

https://www.luogu.org/problemnew/show/U28036

题目描述:

 

题目描述

可爱的古河渚得到了一个序列。她定义一次操作为 将所有的 a_iai​ 变为 a_i+a_{(i\ mod \ n+1)}ai​+a(i mod n+1)​
然后她会向你进行 QQ 次询问,每次问你 x,yx,y ,意义为在第 xx 次操作后位置 yy 的元素是多少。

这个问题太简单了,我们的Nagisa轻易地就解决了这个问题。请问您能解决这个问题吗?

输入输出格式

输入格式:

一个整数 nn ,表示序列的长度。

接下来一行 nn 个整数,表示这个序列。

接下来一行一个整数 QQ ,表示询问次数

接下来 QQ 行,每行两个整数 x,yx,y ,意义如题所示。

输出格式:

共 QQ 行,每行一个整数表示询问的答案,请注意对 998244353998244353 取膜。

输入输出样例

输入样例#1: 复制

5
1 2 3 4 5
2
1 2
2 2

输出样例#1: 复制

5
12

说明

对于 30 \%30% 的数据,满足: 1 \leq n \leq 1001≤n≤100

1 \leq x \leq 1001≤x≤100

1 \leq Q \leq 1001≤Q≤100

对于 50\%50% 的数据:

1\leq n \leq 1000001≤n≤100000

1 \leq x \leq 5001≤x≤500

1 \leq Q \leq 1001≤Q≤100

对于 100 \%100% 的数据,满足

1 \leq n \leq 10^61≤n≤106

1 \leq a_i \leq 10^91≤ai​≤109

1 \leq x \leq 20001≤x≤2000

1 \leq Q \leq 10^41≤Q≤104

解题思路:

        可以用手推数据较小的情况,会发现一些规律,比如

                                          a1                    a2                          a3                            a4                      a5,

                                     a1+a2                  a2+a3                  a3+a4                  a4+a5                 a5+a1

                             a1+2*a2+a3         a2+2*a3+a4         a3+2*a4+a5           a4+2*a5+a6        a5+2*a1+a2

                  a1+3*a2+3*a3+a4    a2+3*a3+3*a4+a5    a3+3*a4+3*a5+a1   a4+3*a5+3*a1+a2   a5+3*a1+3*a2+a3

              通过观察,可以知道操作n次的第i个元素是ai...ai+n,然后每个元素就是乘以C(n,1).....C(n,n);然后就可以了。。

代码:

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<stack>
#include<vector>
#include<cstdio>
#define ll long long
#define inf 1e9
using namespace std;
const int mod=998244353;
const int maxn=1e6+10;
int n,m,su[maxn],sj[2005][2005];
void cl()
{
    for(int i=1;i<=2001;i++)
    sj[i][1]=1,sj[i][i]=1;
    for(int i=3;i<=2001;i++)
        for(int j=2;j<=i-1;j++)
        sj[i][j]=((sj[i-1][j]%mod)+(sj[i-1][j-1]%mod))%mod;
    return ;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&su[i]);
    cl();
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        ll ans=0;
        int cs=a+1,tt=1;
        while(cs--)
        {
            ans+=1ll*su[b++]*sj[a+1][tt++]%mod;
            while(ans>mod)ans-=mod;
            if(b>n)b=1;
        }
        printf("%lld\n",ans%mod);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81432809