题目;http://acm.hdu.edu.cn/showproblem.php?pid=5475

题意就是给X赋初值1,然后给Q个操作,每个操作对应一个整数M;如果操作是1则将X乘以对应的M,如果是2则除以第M次操作对应的M',求最后X的值对给定值取摸的结果,

直接暴力会爆long long,用数组存每一步的话 会超时,所以用线段树优化进行区间更新

 

 1 #include<cstdio>
 2 using namespace std;
 3 typedef long long ll;
 4 struct point {
 5     int l,r;
 6     ll sum;
 7 };
 8 point tree[100001*8];
 9 int n,m;
10 void build(int i,int left,int right)
11 {
12     tree[i].l=left;
13     tree[i].r=right;
14     if (left==right)
15     {
16         tree[i].sum=1;
17         return;
18     }
19     int mid=(left+right)>>1;
20     build(i<<1,left,mid);
21     build(i<<1|1,mid+1,right);
22     tree[i].sum=(tree[i<<1].sum*tree[i<<1|1].sum)%m;
23 }
24 void update(int i,int num,int val)
25 {
26     if (tree[i].l==tree[i].r)
27     {
28         tree[i].sum=val;
29         return;
30     }
31     int mid=(tree[i].l+tree[i].r)>>1;
32     if (num<=mid) update(i<<1,num,val);
33     else update(i<<1|1,num,val);
34     tree[i].sum=(tree[i<<1].sum*tree[i<<1|1].sum)%m;
35 }
36 ll _find(int i,int left,int right)
37 {
38     ll ans=1;
39     if (left<=tree[i].l&&tree[i].r<=right)
40         return tree[i].sum;
41     int mid=(tree[i].l+tree[i].r)>>1;
42     if (left<=mid) ans*=_find(i<<1,left,right)%m;
43     if (right>mid) ans*=_find(i<<1|1,left,right)%m;
44     return ans%m;
45 }
46 int main()
47 {
48     int t,x,y,i,w=1;
49     scanf("%d",&t);
50     while (t--)
51     {
52         printf("Case #%d:\n",w++);
53         scanf("%d %d",&n,&m);
54         build(1,1,n);
55         for (i=1;i<=n;i++)
56         {
57             scanf("%d %d",&x,&y);
58             if (x==1)
59             {
60                 update(1,i,y);
61                 printf("%I64d\n",_find(1,1,i)%m);
62             }
63             else
64             {
65                 update(1,y,1);
66                 printf("%I64d\n",_find(1,1,i)%m);
67             }
68         }
69     }
70     return 0;
71 }

 

posted on 2015-09-29 20:57  蜘蛛侦探  阅读(120)  评论(0编辑  收藏  举报