zoukankan      html  css  js  c++  java
  • (容斥)Codeforces Round #428 (Div. 2) D. Winter is here

    D. Winter is here
    time limit per test
    3 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Winter is here at the North and the White Walkers are close. John Snow has an army consisting of n soldiers. While the rest of the world is fighting for the Iron Throne, he is going to get ready for the attack of the White Walkers.

    He has created a method to know how strong his army is. Let the i-th soldier’s strength be ai. For some k he calls i1, i2, ..., ik a clan if i1 < i2 < i3 < ... < ik and gcd(ai1, ai2, ..., aik) > 1 . He calls the strength of that clan k·gcd(ai1, ai2, ..., aik). Then he defines the strength of his army by the sum of strengths of all possible clans.

    Your task is to find the strength of his army. As the number may be very large, you have to print it modulo 1000000007 (109 + 7).

    Greatest common divisor (gcd) of a sequence of integers is the maximum possible integer so that each element of the sequence is divisible by it.

    Input

    The first line contains integer n (1 ≤ n ≤ 200000) — the size of the army.

    The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1000000) — denoting the strengths of his soldiers.

    Output

    Print one integer — the strength of John Snow's army modulo 1000000007 (109 + 7).

    Examples
    Input
    3
    3 3 1
    Output
    12
    Input
    4
    2 3 4 6
    Output
    39
    Note

    In the first sample the clans are {1}, {2}, {1, 2} so the answer will be 1·3 + 1·3 + 2·3 = 12

    和今年多校之前一场的一道题目处理方法很相似。考虑每个gcd,如果某序列满足gcd整除该序列的每一个数,那么这个gcd就一定整除该序列的真正最大公因数。对于某数x,求x整除序列中每一个数的序列显然比求x为序列gcd的序列个数容易的多,并且它们是有一定关系的,所以先求出对于每一个x,整除序列中每一个数的序列个数。显然序列中的数都得从被x整除的数中选取,设有cnt个,则序列个数即为

    下面计算gcd的序列时采用从后往前做的策略,这样就可以有效避免自己正序写容斥的麻烦,因为我们从后往前求到现在求过的每一个数都是保证gcd恰好为此的序列个数,当前未求到的数x对应表示的是序列gcd为x,2*x,3*x……的个数之和,只需要把已经求出的部分全部减掉即可,得到的便是gcd为x的序列个数了。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <vector>
     5 #include <set>
     6 #include <map>
     7 #include <string>
     8 #include <cstring>
     9 #include <stack>
    10 #include <queue>
    11 #include <cmath>
    12 #include <ctime>
    13 #include<bitset>
    14 #include <utility>
    15 using namespace std;
    16 #define REP(I,N) for (I=0;I<N;I++)
    17 #define rREP(I,N) for (I=N-1;I>=0;I--)
    18 #define rep(I,S,N) for (I=S;I<N;I++)
    19 #define rrep(I,S,N) for (I=N-1;I>=S;I--)
    20 #define FOR(I,S,N) for (I=S;I<=N;I++)
    21 #define rFOR(I,S,N) for (I=N;I>=S;I--)
    22 #define rank rankk
    23 #define DFT FFT
    24 typedef unsigned long long ull;
    25 typedef long long ll;
    26 const int INF=0x3f3f3f3f;
    27 const ll INFF=0x3f3f3f3f3f3f3f3fll;
    28 //const ll M=1e9+7;
    29 const ll maxn=2e5+7;
    30 const int MAXN=1005;
    31 const int MAX=1e6+5;
    32 const int MAX_N=MAX;
    33 const int N=55;
    34 const ll MOD=1e9+7;
    35 //const double eps=0.00000001;
    36 int gcd(int a,int b){return b?gcd(b,a%b):a;}
    37 template<typename T>inline T abs(T a) {return a>0?a:-a;}
    38 inline ll powMM(ll a,ll b,ll M){
    39     ll ret=1;
    40     a%=M;
    41 //    b%=M;
    42     while (b){
    43         if (b&1) ret=ret*a%M;
    44         b>>=1;
    45         a=a*a%M;
    46     }
    47     return ret;
    48 }
    49 void open()
    50 {
    51     freopen("1004.in","r",stdin);
    52     freopen("out.txt","w",stdout);
    53 }
    54 int n;
    55 int num[MAX],tem,cnt[MAX],who,ans[MAX];
    56 int an;
    57 set<int>s;
    58 set<int>::iterator it;
    59 int main()
    60 {
    61     scanf("%d",&n);
    62     for(int i=1;i<=n;i++)
    63     {
    64         scanf("%d",&tem);
    65         num[tem]++;
    66         s.insert(tem);
    67     }
    68     for(it=s.begin();it!=s.end();it++)
    69     {
    70         who=*it;
    71         for(int i=1;i*i<=who;i++)
    72         {
    73             if(who%i==0)
    74             {
    75                 cnt[i]+=num[who];
    76                 if(i*i!=who)
    77                     cnt[who/i]+=num[who];
    78             }
    79         }
    80     }
    81 //    printf("who=%d
    ",who);
    82     for(int j=who;j>=2;j--)
    83     {
    84 //        printf("~~%d %d
    ",j,cnt[j]);
    85         if(!cnt[j])
    86             continue;
    87         ans[j]=(ll)powMM(2LL,(ll)cnt[j]-1,MOD)*cnt[j]%MOD;
    88 //        printf("fin
    ");
    89         for(int i=2;i*j<=who;i++)
    90         {
    91 //            printf("!!%d %d
    ",i,i*j);
    92             ans[j]=(ans[j]-ans[i*j]+MOD)%MOD;
    93         }
    94         an=(an+(ll)j*ans[j]%MOD)%MOD;
    95 //        printf("!!
    ");
    96     }
    97     printf("%d
    ",an);
    98     return 0;
    99 }
  • 相关阅读:
    WEB学习-CSS行高、字体,链接的美化以及背景
    WEB学习-CSS中Margin塌陷
    Java反射02 : Class对象获取的三种方式和通过反射实例化对象的两种方式
    Java反射01 : 概念、入门示例、用途及注意事项
    对于写Java的博文
    C++ 运算符优先级列表
    android笔记--Intent和IntentFilter详解
    C语言、指针(一)
    switch...case...语句分析(大表跟小表何时产生)
    SourceInsight教程
  • 原文地址:https://www.cnblogs.com/quintessence/p/7354412.html
Copyright © 2011-2022 走看看