zoukankan      html  css  js  c++  java
  • 51 Nod 1678 lyk与gcd

    基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题

    这天,lyk又和gcd杠上了。
    它拥有一个n个数的数列,它想实现两种操作。


    1:将  ai 改为b。
    2:给定一个数i,求所有 gcd(i,j)=1 时的  aj  的总和。

    Input
    第一行两个数n,Q(1<=n,Q<=100000)。
    接下来一行n个数表示ai(1<=ai<=10^4)。
    接下来Q行,每行先读入一个数A(1<=A<=2)。
    若A=1,表示第一种操作,紧接着两个数i和b。(1<=i<=n,1<=b<=10^4)。
    若B=2,表示第二种操作,紧接着一个数i。(1<=i<=n)。
    Output
    对于每个询问输出一行表示答案。
    Input示例
    5 3
    1 2 3 4 5
    2 4
    1 3 1
    2 4
    Output示例
    9
    7
     1 #include<vector>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 #define N 100010
     6 #define LL long long
     7 vector<int>f[N],g[N];
     8 int a[N],n,ques;
     9 bool q[N];
    10 long long sum[N];
    11 void Prepare(){
    12     int cnt=0;
    13     for(int i=2;i<=n;i++){
    14         if(!q[i])a[++cnt]=i;
    15         for(int j=1;j<=cnt;j++){
    16             if(a[j]*i>n) break;
    17             q[a[j]*i]=1;
    18             if(i % a[j] == 0) break;
    19         }
    20     }
    21     for(int i=1;i<=cnt;i++){
    22         for(int j=a[i];j<=n;j+=a[i]){
    23             int w=f[j].size();
    24             for(int k=0;k<w;k++){
    25                 f[j].push_back(f[j][k]*a[i]);
    26                 g[j].push_back(g[j][k]+1);
    27             }
    28             f[j].push_back(a[i]);
    29             g[j].push_back(1);
    30         }
    31     }
    32 }
    33 int main()
    34 {
    35     LL ans;
    36     scanf("%d%d",&n,&ques);
    37     Prepare();
    38     for(int i=1;i<=n;i++){
    39         scanf("%d",&a[i]);sum[1]+=a[i];
    40         for(int j=0;j<f[i].size();j++)
    41             sum[f[i][j]]+=a[i];
    42     }
    43     int x,pos,value;
    44     while(ques--){
    45         scanf("%d",&x);
    46         if(x==1){
    47             scanf("%d%d",&pos,&value);
    48             for(int i=0;i<f[pos].size();i++)
    49                 sum[f[pos][i]]-=a[pos];
    50             sum[1]-=a[pos];a[pos]=value;sum[1]+=a[pos];
    51             for(int i=0;i<f[pos].size();i++)
    52                 sum[f[pos][i]]+=a[pos];
    53         }
    54         else{
    55             ans=sum[1];
    56             scanf("%d",&pos);
    57             for(int i=0;i<f[pos].size();i++)
    58                 if(g[pos][i] & 1)ans-=sum[f[pos][i]];
    59                 else ans+=sum[f[pos][i]];
    60             
    61             printf("%lld
    ",ans);
    62         }
    63     }
    64     return 0;
    65 }

    比较基础的容斥题,我们预处理出每个i的所有素因子的组合,比如6={2,3,6},那么我们对于a[6]将它加入到sum[2],sum[3],sum[6]中,统计答案时用容斥思想加加减减就行了。

     
  • 相关阅读:
    php 计算两个日期相差天数
    Linux系统查找清理磁盘大文件
    虚拟机重启网络服务失败,当查看状态显示错误Failed to start LSB......
    c++简单编写线性表(实验)
    学校的c++程序课程设计(简单的写法 并无太多c++的特色)
    C语言简单实现链栈基本几个功能
    简单用数组模拟顺序栈(c++)
    详细易懂的二叉树遍历(先中后)
    大数加法之C语言函数法(只有正数版)
    有关Java垃圾回收的几个问题
  • 原文地址:https://www.cnblogs.com/suishiguang/p/6435145.html
Copyright © 2011-2022 走看看