题目来源:
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;
}