约数个数的和
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给个n,求1到n的所有数的约数个数的和~
输入描述:
第一行一个正整数n
输出描述:
输出一个整数,表示答案
示例1
输入
3
输出
5
说明
样例解释:
1有1个约数1
2有2个约数1,2
3有2个约数1,3
备注:
n <= 100000000
就是结论啊。因子i的个数就是n/i。还以为是这些因子的和
#include<bits/stdc++.h> using namespace std; int main() { int n; scanf("%d",&n); long long ans=0; for(int i=1; i<=n; ++i) ans+=n/i; printf("%lld",ans); return 0; }
储物点的距离
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
一个数轴,每一个储物点会有一些东西,同时它们之间存在距离。
每次给个区间[l,r],查询把这个区间内所有储物点的东西运到另外一个储物点的代价是多少?
比如储物点i有x个东西,要运到储物点j,代价为x * dist( i , j )
dist就是储物点间的距离。
每次给个区间[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 5 2 3 4 5 1 2 3 4 5 1 1 5 3 1 5 2 3 3 3 3 3 1 5 5
输出
125 72 9 0 70
备注:
对于100%的数据n,m <= 200000 , 0 <= ai,bi <= 2000000000
用前缀和处理,直接查询
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=200005,MD=1e9+7; ll l[N],r[N],ld[N],rd[N],s[N],b[N],dis[N],xx,ans,n,m; ll gets(int L,int R) { return (s[R]-s[L-1])%MD; } ll ql(int L,int R,int x) { return (l[R]-l[L-1]-gets(L,R)*ld[x])%MD; } ll qr(int L,int R,int x) { return (r[L]-r[R+1]-gets(L,R)*rd[x])%MD; } int main() { scanf("%d%d",&n,&m); for(int i=1; i<n; ++i) scanf("%lld",&dis[i]); for(int i=1; i<=n; ++i) scanf("%lld",&b[i]); for(int i=2; i<=n; i++) { ld[i]=(dis[i-1]+ld[i-1])%MD; l[i]=(l[i-1]+b[i]*ld[i])%MD; } for(int i=n-1; i>=1; i--) { rd[i]=(dis[i]+rd[i+1])%MD; r[i]=(r[i+1]+b[i]*rd[i])%MD; } for(int i=1; i<=n; i++) s[i]=(s[i-1]+b[i])%MD; for(int i=1,x,l,r; i<=m; ++i) { scanf("%d%d%d",&x,&l,&r); if(x<=l) ans=ql(l,r,x); else if(x>=r) ans=qr(l,r,x); else ans=(ql(x+1,r,x)+qr(l,x-1,x))%MD; printf("%lld\n",(ans+MD)%MD); } return 0; }
加边的无向图
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给你一个 n 个点,m 条边的无向图,求至少要在这个的基础上加多少条无向边使得任意两个点可达~
输入描述:
第一行两个正整数 n 和 m 。
接下来的m行中,每行两个正整数 i 、 j ,表示点i与点j之间有一条无向道路。
输出描述:
输出一个整数,表示答案
示例1
输入
4 2 1 2 3 4
输出
1
备注:
对于100%的数据,有n,m<=100000。
直接bfs联通块就行
#include<bits/stdc++.h> using namespace std; const int N=1e6+5; int g[N],nxt[N],a[N],tot,vis[N],ans,n,m; queue<int>q; void add(int x,int y) { a[++tot]=y,nxt[tot]=g[x],g[x]=tot; } void bfs() { int x=q.front(); q.pop(); for(int i=g[x]; i; i=nxt[i]) if(!vis[a[i]]) vis[a[i]]=1,q.push(a[i]); } int main() { cin>>n>>m; for(int i=0,a,b; i<m; i++) { cin>>a>>b; add(a,b),add(b,a); } for(int i=1; i<=n; i++) if(!vis[i]) { ans++; q.push(i); while(q.size())bfs(); } cout<<ans-1; return 0; }
集合中的质数
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给出一个集合和一个数m。
集合里面有n个质数。
请你求出从 1 到 m 的所有数中,至少能被集合中的一个数整除的数的个数。
输入描述:
第一行两个正整数 n 和 m 。
第二行n个正整数,分别为集合中的质数。
输出描述:
输出一个整数,表示符合要求的正整数的个数。
示例1
输入
3 37 5 7 13
输出
13
备注:
对于100%的数据,有n<=20,m为有符号64位正整数,集合内质数<=1000000000
容斥裸题,但是会爆LL啊,我用了__int128,其实这种爆数据范围呢,都可以转换,加变减乘变除就行了啊
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n,m; ll ans,a[21]; __int128 gcd(__int128 a,__int128 b){ return b==0?a:gcd(b,a%b); } void DFS(int cur,__int128 lcm,int id) { if(lcm>n)return; lcm=a[cur]/gcd(a[cur],lcm)*lcm; if(id&1) ans+=n/lcm; else ans-=n/lcm; for(int i=cur+1; i<m; i++) DFS(i,lcm,id+1); } int main() { scanf("%lld%lld",&m,&n); for(ll i=0; i<m; i++) scanf("%I64d",&a[i]); ans=0; for(ll i=0; i<m; i++) DFS(i,a[i],1); printf("%lld\n",ans); return 0; }