题目描述
给定一个由n个整数构成的序列,你需要对它进行如下操作:
操作1:输入格式“1 x y”,表示把所有a[kx](k为正整数,kx<=n)都加上y。
操作2:输入格式“2 j”,表示输出a[j]。
输入输出格式
输入格式:
第一行,两个数n,m,表示有n个数,m条操作。
第二行,n个数a[1],a[2],…,a[n]。
接下来m行,为m条操作。
输出格式:
输出若干行,每行对应一次操作2。
输入输出样例
说明
对于40%的数据,n<=100
对于100%的数据,n<=1000000,m<=100000,|a[i]|<=1000000,|y|<=1000000,x<=n,j<=n,操作2不超过10000条。
Solution:
本题不需要什么特别厉害的数据结构。我们直接进行模拟,对于1操作,统计一下那些数的倍数被修改,当2操作查询时直接开根枚举因子并修改,唯一要注意的是当i*i==x时只要加1次,其它的话两个因子都要累加。可以算一波复杂度:O(m√n),因为最多查询10000次,而数最大为1000000,所以最坏情况也就107
代码:
1 // luogu-judger-enable-o2 2 #include<bits/stdc++.h> 3 #define il inline 4 #define ll long long 5 using namespace std; 6 const int N=1000005; 7 il int gi() 8 { 9 int a=0;char x=getchar();bool f=0; 10 while((x<‘0‘||x>‘9‘)&&x!=‘-‘)x=getchar(); 11 if(x==‘-‘)x=getchar(),f=1; 12 while(x>=‘0‘&&x<=‘9‘)a=a*10+x-48,x=getchar(); 13 return f?-a:a; 14 } 15 ll a[N],n,m,tot[N]; 16 int main() 17 { 18 n=gi(),m=gi(); 19 for(int i=1;i<=n;i++)a[i]=gi(); 20 int k,x,y; 21 while(m--){ 22 scanf("%lld",&k); 23 if(k==2){x=gi(); 24 ll ans=0; 25 for(int i=1;i*i<=x;i++) 26 if(x%i==0){i*i==x?ans+=tot[i]:ans+=tot[i]+tot[x/i];} 27 printf("%lld\n",a[x]+ans); 28 } 29 else { 30 x=gi();y=gi();tot[x]+=y; 31 } 32 } 33 return 0; 34 }