牛客练习赛8

来源:互联网 发布:什么叫网络级防火墙 编辑:程序博客网 时间:2024/05/15 01:07

约数个数的和

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给个n,求1到n的所有数的约数个数的和~

输入描述:

第一行一个正整数n

输出描述:

输出一个整数,表示答案
示例1

输入

3

输出

5

说明

样例解释:1有1个约数12有2个约数1,23有2个约数1,3

备注:

n <= 100000000
#include<iostream>using namespace std;int main(){    long long n,ans=0;    cin>>n;    for(long long i=1;i<=n/2;i++)    {        ans+=n/i;    }    ans+=n-n/2;    cout<<ans<<endl;    return 0;}

储物点的距离

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述


 一个数轴,每一个储物点会有一些东西,同时它们之间存在距离。
每次给个区间[l,r],查询把这个区间内所有储物点的东西运到另外一个储物点的代价是多少?
比如储物点i有x个东西,要运到储物点j,代价为x * dist( i , j )
dist就是储物点间的距离。 


输入描述:

第一行两个数表示n,m

第二行n-1个数,第i个数表示第i个储物点与第i+1个储物点的距离ai

第三行n个数,表示每个储物点的东西个数bi

之后m行每行三个数x l r

表示查询要把区间[l,r]储物点的物品全部运到储物点x的花费
每次查询独立

输出描述:

对于每个询问输出一个数表示答案答案对1000000007取模
示例1

输入

5 52 3 4 51 2 3 4 51 1 53 1 52 3 33 3 31 5 5

输出

125729070

备注:

对于100%的数据n,m <= 200000 , 0 <= ai,bi <= 2000000000

#include<bits/stdc++.h>using namespace std;#define N 200010#define mo 1000000007int a[N];long long dis[N],sum[N],cnt[N];int main(){    int n,m,i;    scanf("%d%d",&n,&m);    for (i=2;i<=n;i++) scanf("%d",&a[i]);    for (i=1;i<=n;i++) dis[i]=(dis[i-1]+a[i])%mo;    for (i=1;i<=n;i++){        int x;        scanf("%d",&x);        cnt[i]=(cnt[i-1]+x)%mo;        sum[i]=(sum[i-1]+x*dis[i])%mo;    }    for (i=1;i<=m;i++){        long long ans=0;        int x,l,r;        scanf("%d%d%d",&x,&l,&r);        if (l>x) ans=sum[r]-sum[l-1]-dis[x]*(cnt[r]-cnt[l-1])%mo;        else if (r<x) ans=dis[x]*(cnt[r]-cnt[l-1])%mo-(sum[r]-sum[l-1]);        else ans=sum[r]-sum[x]-dis[x]*(cnt[r]-cnt[x])%mo+dis[x]*(cnt[x-1]-cnt[l-1])%mo-(sum[x-1]-sum[l-1]);        printf("%lld\n",(ans%mo+mo)%mo);    }    return 0;}

加边的无向图

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给你一个 n 个点,m 条边的无向图,求至少要在这个的基础上加多少条无向边使得任意两个点可达~ 

输入描述:

第一行两个正整数 n 和 m 。接下来的m行中,每行两个正整数 i 、 j ,表示点i与点j之间有一条无向道路。

输出描述:

输出一个整数,表示答案
示例1

输入

4 21 23 4

输出

1

备注:

对于100%的数据,有n,m<=100000。
#include<iostream>#include<cstdio>using namespace std;long n,m,ans,f[100050];long find(long x){     return f[x]==x?x:f[x]=find(f[x]);}int main(){    scanf("%ld%ld",&n,&m);    for(long i=1;i<=n;i++)    {        f[i]=i;    }    for(long i=1;i<=m;i++)    {        long x,y;        scanf("%ld%ld",&x,&y);        f[find(x)]=find(y);    }    for(long i=1;i<=n;i++)    {        if(f[i]==i)            ans++;    }    cout<<ans-1<<endl;    return 0;}

集合中的质数

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给出一个集合和一个数m。

集合里面有n个质数。

请你求出从 1 到 m 的所有数中,至少能被集合中的一个数整除的数的个数。

输入描述:

第一行两个正整数 n 和 m 。第二行n个正整数,分别为集合中的质数。

输出描述:

输出一个整数,表示符合要求的正整数的个数。
示例1

输入

3 375 7 13

输出

13

备注:

对于100%的数据,有n<=20,m为有符号64位正整数,集合内质数<=1000000000
没做出来,别人的代码==
#include "stdio.h"int main(){    int n ;    long long int m ;    scanf("%d %lld" , &n ,&m );    int value[n] ;    for(int i = 0; i < n ; i ++)    {        scanf("%d" , &value[i]) ;    }    long long result = 0 ;    for(int i = 0 ; i < (1<< n) ; i ++)    {        int count = 0 ;        long long sum = 1 ;        for(int j = 0 ; j < n ;  j ++) {            if(i & (1<<j))            {                sum*= value[j] ;                count ++ ;            }        }        if( count & 1 )            result += m/sum ;        else if( count )            result -= m/sum ;    }    printf("%lld" , result) ;}