acdream 1071 神奇的%系列一 (树状数组维护,离散化)

来源:互联网 发布:淘宝怎么买微博小号 编辑:程序博客网 时间:2024/06/08 07:23

题意:

给出一个序列,求这个序列中满足i!=j&&a[i]%a[j]!=0的个数。

题解:

其实逆问题跟容易求,我们先求a[i]%a[j]==0的个数,然后用总的个数-这个值。总的个数可以用树状数组维护,a[i]%a[j]==0的个数可以枚举每个a[j],然后得到a[j]的倍数从而统计。

#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#include<map>#include<set>#define B(x) (1<<(x))using namespace std;typedef long long ll;typedef unsigned long long ull;void cmax(int& a,int b){ if(b>a)a=b; }void cmin(int& a,int b){ if(b<a)a=b; }void cmax(ll& a,ll b){ if(b>a)a=b; }void cmin(ll& a,ll b){ if(b<a)a=b; }void add(int& a,int b,int mod){ a=(a+b)%mod; }void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }const int oo=0x3f3f3f3f;const ll OO=0x3f3f3f3f3f3f3f3f;const ll MOD=1000000007;const int maxn = 100005;int a[maxn],num[maxn];int tree[maxn];void Init(){    memset(tree,0,sizeof tree);    memset(num,0,sizeof num);}int lowbit(int x){    return x&(-x);}void updata(int x){    for(int i=x;i<maxn;i+=lowbit(i))        tree[i]+=1;}int get_sum(int x){    int sum=0;    for(int i=x;i>=1;i-=lowbit(i))        sum+=tree[i];    return sum;}int main(){    int n;    while(scanf("%d",&n)!=EOF){        Init();        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);            num[a[i]]++;            updata(a[i]);        }        ll ans=0;        for(int i=1;i<=n;i++){            ll res=0;            for(int j=a[i]+a[i];j<=100000;j+=a[i])                res+=num[j];            ans+=(n-get_sum(a[i]))-res;        }        cout<<ans<<endl;    }    return 0;}



0 0
原创粉丝点击