https://www.luogu.org/problemnew/show/P1483
给定一个长度为 n n 的序列,要求支持以下操作
1. 支持编号是 x x 的倍数的所有数同时加上 y y
2. 输出编号为 x x 的数
比较容易想到一种朴素的思路
维护一个数组 b b , bi b i 表示 i i 这个位置的增值,然后在修改的时候暴力改,时间复杂度最坏为 O(mn) O ( m n ) ,此方法可拿70分
又想到另一种 O(1) O ( 1 ) 修改,考虑优化回答的方法,首先预处理所有数的因数,然后回答的时候找到 x x 的所有因数,加上其对应的 bi b i 即可
这种方法的理论时间复杂度为 O(nlogn+mlogn) O ( n l o g n + m l o g n ) ,由于常数大了一点,所以只能拿70
考虑去优化上面的方法,回答的时候直接加上这个编号的因数上的 b b ,即可求出最终答案,时间复杂度最坏为 O(nm−−√) O ( n m ) ,可以卡过本题。
#include
using namespace std;int n,m,a[1000001],x,y,b[1000001],k;
int read()
{
char c;int d=1,f=0;
while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>47&&c<58)f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register int x){if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+48);return;}
signed main()
{
n=read();m=read();
for(register int i=1;i<=n;i++) a[i]=read();
while(m--)
{
k=read()-1;
if(k)
{
x=read();
write(a[x]+b[x]);putchar(10);//O(1)回答
}
else
{
x=read();y=read();
for(register int j=x;j<=n;j+=x) b[j]+=y;//朴素更改
}
}
}
#include
#include
using namespace std;int n,m,a[1000001],x,y,b[1000001],ans,k;
vector<int>factor[1000001];
int read()
{
char c;int d=1,f=0;
while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>47&&c<58)f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register int x){if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+48);return;}
signed main()
{
n=read();m=read();
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n/i;j++)
factor[i*j].push_back(i);//预处理
for(register int i=1;i<=n;i++) a[i]=read();
while(m--)
{
k=read()-1;
if(k)
{
x=read();
ans=a[x];
for(register int i=0;i//找到约数并且输出
write(ans);putchar(10);
}
else x=read(),y=read(),b[x]+=y;
}
}
#include
using namespace std;int n,m,a[1000001],x,y,b[1000001],ans,k;
int read()
{
char c;int d=1,f=0;
while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>47&&c<58)f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register int x){if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+48);return;}
signed main()
{
n=read();m=read();
for(register int i=1;i<=n;i++) a[i]=read();
while(m--)
{
k=read()-1;
if(k)
{
x=read();
ans=a[x];
for(register int i=1;i*i<=x;i++)
{
if(x%i) continue;//找到是x因数的数
ans+=b[i];if(i!=x/i) ans+=b[x/i];//因为因数都是成对出现的,所以可以直接加,注意判断完全平方数
}
write(ans);putchar(10);
}
else x=read(),y=read(),b[x]+=y;//O(1)修改
}
}