小白赛,,codeforces,计蒜课

小白赛5:

A题意:

 若一个集合A内所有的元素都不是正整数N的因数,则称N与集合A无关。

  给出一个含有k个元素的集合A={a1,a2,a3,...,ak},求区间[L,R]内与A无关的正整数的个数。  保证A内的元素都是素数

1<=L<=R<=10^18,1<=k<=20,2<=ai<=100

题解:用相容定理找出有关的数相减

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
#define LL unsigned long long
const int maxn = 1e2+3;
LL l,r,k;
LL a[maxn];
 
LL sum=0;
void dfs(LL x,LL now,LL c)
{
    if(x>r) return;
    if(c&1){
        sum+=r/x-(l-1)/x;
    }else{
        sum-=r/x-(l-1)/x;
    }
    for(LL i=now+1;i<=k;i++){
        dfs(x*a[i],i,c+1);
    }
}
 
int main()
{
 
    while(~scanf("%llu%llu%llu",&l,&r,&k)){
        sum=0;
        for(LL i=1;i<=k;i++)
            scanf("%llu",&a[i]);
        for(LL i=1;i<=k;i++)
            dfs(a[i],i,1);
        printf("%llu\n",(r-l+1)-sum);
    }
}

I:

链接:https://www.nowcoder.com/acm/contest/135/I

theme:有一个n个元素的数组a,而他要对a[L]-a[R]进行M次操作:        操作一:将a[L]-a[R]内的元素都加上P        操作二:将a[L]-a[R]内的元素都减去P   最后询问a[l]-a[r]内的元素之和?

solution:线段树超内存 400万32兆吃力,这题只算一次区间和,直接用前缀和

前缀和AC代码:

#include<iostream>
using namespace std;

typedef long long ll;
int const SIZE=1000010;

ll a[SIZE];

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;++i)
        cin>>a[i];
        
/*对数组初始化为该项与前一项的和*/

    for(int i=n;i>1;--i)
        a[i]=a[i]-a[i-1];
        
    int q,l,r,p;
    
/*区间修改只对左边界(增加则加)和右边界后一个(增加则减)修改*/
    while(m--)
    {
        cin>>q>>l>>r>>p;
        if(q==1)
            a[l]-=p,a[r+1]+=p;
        else
            a[l]+=p,a[r+1]-=p;
    }
    cin>>l>>r;
    ll sum=0;
    
/*最后还原求区间和时一定要从头开始加,每一项等于本身加上前一项*/    
    for(int i=2;i<=n;++i)
        a[i]=a[i]+a[i-1];
        
    for(int i=l;i<=r;++i)
        sum+=a[i];
    cout<<sum<<endl;
}

附上线段树代码:

#include<iostream>
using namespace std;

typedef long long ll;
int const SIZE=1000010;

struct tree
{
    int bj;
    int sum;
}T[4*SIZE];

int a[SIZE];

void build(int k,int l,int r)
{
    T[k].bj=0;
    if(l==r)
    {
        cin>>a[l];
        T[k].sum=a[l];
    }
    else
    {
        int mid=(l+r)/2;
        build(k<<1,l,mid);
        build((k<<1)+1,mid+1,r);
        T[k].sum=T[k<<1].sum+T[(k<<1)+1].sum;
    }
}

void update(int k,int l1,int r1,int l2,int r2)
{
    T[k<<1].sum+=T[k].bj*(r1-l1+1);
    T[(k<<1)+1].sum+=T[k].bj*(r2-l2+1);
    T[k<<1].bj+=T[k].bj;
    T[(k<<1)+1].bj+=T[k].bj;
    T[k].bj=0;
}

void add(int k,int s,int e,int delta,int l,int r)
{
    if(s==l&&r==e)
    {
        T[k].sum+=delta*(r-l+1);
        T[k].bj+=delta;
    }
    else
    {
        int mid=(l+r)/2;
        if(T[k].bj)update(k,l,mid,mid+1,r);
        if(e<=mid)
            add(k<<1,s,e,delta,l,mid);
        else if(s>mid)
            add((k<<1)+1,s,e,delta,mid+1,r);
        else
            {
                add(k<<1,s,mid,delta,l,mid);
                add((k<<1)+1,mid+1,e,delta,mid+1,r);
            }
        T[k].sum=T[k<<1].sum+T[(k<<1)+1].sum;
    }
}

ll query(int k,int s,int e,int l,int r)
{
    if(l==s&&r==e)return T[k].sum;
    int mid=(l+r)/2;
    if(T[k].bj)update(k,l,mid,mid+1,r);
    ll ans=0;
    if(e<=mid)
        ans+=query(k<<1,s,e,l,mid);
    else if(s>mid)
       ans+=query((k<<1)+1,s,e,mid+1,r);
    else
       ans+=query(k<<1,s,mid,l,mid)+query((k<<1)+1,mid+1,e,mid+1,r);
    return ans;
}

int main()
{
    int n,m;
    cin>>n>>m;
    build(1,1,n);    
    int q;
    int l,r,p;
    while(m--)
    {
        cin>>q>>l>>r>>p;
        if(q==1)
           add(1,l,r,-p,1,n);
        else
            add(1,l,r,p,1,n);
    }
    cin>>l>>r;
    ll ans;
    ans=query(1,l,r,1,n);
    cout<<ans;
}

codeforces497

A:theme:对数组进行某种排序后,最多有多少个元素
  现在的数值比之前大?
  Input
  The first line contains a single integer n (1≤n≤10^5) — the length of the array.
  The second line contains n integers (1≤ai≤109) — the elements of the array.

#include<iostream>
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;

int const SIZE=100010;
typedef long long ll;
vector<ll>a;

int main()
{
    int n,cnt=0;
    cin>>n;
    for(int i=0;i<n;++i)
      {
         ll v;
         scanf("%lld",&v);
         a.push_back(v);
      }
    sort(a.begin(),a.end());
    int i=n-2,j=n-1;
    while(i!=-1)
    {
        if(a[i]<a[j])
        {
            --i;
            --j;
            ++cnt;
        }
        else --i;
    }
    printf("%d",cnt);
}
​
​
​
#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9+7;

int main( ) {
    int  n, x, y;

    while (scanf("%d", &n) == 1) {
        map<int,int> diag1, diag2;
        long         res = 0;
        for (int i = 0; i < n; ++i) {
            scanf("%d%d", &x, &y);
            int d1 = x + y;
            int d2 = x - y;
            res += diag1[d1];//这样处理顺便求了和(里面的点任意两个都可以组成一对)
            res += diag2[d2];//即求C(n,2),就是从1加到n-1,不用加n,所以res+在++前
            ++diag1[d1];
            ++diag2[d2];
        }
        printf("%.8f\n", 2.0 * res / n / n);
    }
    return 0;
}

​

​

​

计蒜课ctu2017 Go Northwest

中心题意为给定多个点的坐标,求出互为西北东北方向(即在对角,45度)的点对数

solution:给定坐标(a,b)就可得两条直线y-x=b-a ,y+x=b+a;则只要同样满足这两个方程其中之一(即在同一条直线上,即右边相同)的点都满足:注意只能是b-a,(不是绝对值,这是不同类了),所以用map 可允许d2[t2]中,t2为负

猜你喜欢

转载自blog.csdn.net/wangqianqianya/article/details/81166428
今日推荐