Time Limit: 12000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2482 Accepted Submission(s): 953 Problem Description Give you three integers n, A and B.
Input Each line will contain three integers n(1 <= n <= 107),A and B(1 <= A, B <= 231-1).
Output For each case, output the answer in a single line.
Sample Input 1 2 3 2 3 4 3 4 5 4 5 6 5 6 7
Sample Output 2 3 4 5 6
Author WhereIsHeroFrom@HDU
Source
Recommend lcy
|
题目大意:每一组数据给出三个整数 n、A、B,定义 Si=Ai % B,Ti=Min{ Sk | i-A<=k<=i,k>=1 },求 T1*T2*...*Tn % B,1<=i<=n
思路:Ti 实际上就是在大小为 k 的区间中最小的数字,因此可以维护一个递增的单调队列,每次将一个新值放进队列,将队尾的值与这个值比较,若大于等于则队尾出队,若队首的下标差大于 A 也出队,这样一来相当于每次都是将一个新的值放入队列,然后拿队首一个最小的作为当前的 Ti,一边更新一边记录,
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#define ll long long
using namespace std;
struct Node
{
int pos;
ll num;
Node(int pos,ll num):pos(pos),num(num){}
};
int main()
{
int n,a,b;
while(scanf("%d%d%d",&n,&a,&b)!=EOF&&n+a+b)
{
deque<Node>Q;
ll res=1,S=1;
for(int i=1;i<=n;i++)
{
S=S*a%b;
while(!Q.empty()&&Q.back().num>=S)
Q.pop_back();
Q.push_back(Node(i,S));
while(!Q.empty()&&Q.front().pos<i-a)
Q.pop_back();
res=res*Q.front().num%b;
}
printf("%lld\n",res);
}
return 0;
}