本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:
Problem A. Divisors(div.c/cpp/pas)
Input fifile: div.in
Output fifile: div.out
Time limit: 1 seconds
Memory limit: 128 megabytes
给定 m 个不同的正整数 a1, a2, ..., am,请对 0 到 m 每一个 k 计算,在区间 [1, n] 里有多少正整数
是 a 中恰好 k 个数的约数。
Input
第一行包含两个正整数 n, m,分别表示区间范围以及 a 数组的大小。
第二行包含 m 个不同的正整数 a1, a2, ..., am,表示 a 数组。
Output
输出 m + 1 行,每行一个整数,其中第 i 行输出 k = i 的答案。
Examples
div.in div.out
样例一
输入:
10 3
4 6 7
输出:
4
4
1
1
样例二
输入:
5 1
8
输出:
2
3
题目意思有点小恶心,大意如下:
令1到n中正整数为S
取区间[1,n], 1到n中正整数。 看S中是否满足数组a中所有数,S有几个为数组a中这些数的k个约数。
k=0到m
样例解释如下:
样例一:
第一行:为k=0,所以用总数减去其余行数的答案,即:10-4-1-1=4 所以 答案为4
第二行:为k=1时,其中:3,4,6,7符合题意,刚好在a中都只有一个约数(约数间无交集) 答案为4
第三行:为k=2时,其中:2 符合题意,只有2同时是在a中的4和6的约数(2个共同的约数) 答案为1
第三行:为k=3时,其中:1 符合题意,只有1同时是在a中的4,6,7共同的约数(3个共同的约数) 答案为1
在1到10中,只有1是a中3个数的约数,2是a中2个数的约数,3,4,6,7分别是a中一个数的约数
样例二:
第一行:为k=0,以用总数减去其余行数的答案,即:5-3=2 所以 答案为2
第二行:为k=1时,其中:1,2,4 既是8的一个约数,有在区间[1,5]中,所以符合题意 答案为3
在1到5中,只有1,2,4是a中1个数的约数
code:
#include<bits/stdc++.h> #pragma GCC optimize(3) #define N 10000010 using namespace std; int n,m,tot,sum; int a[N],p[N],yzl[N]; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } void inint(){ freopen("div.in","r",stdin); freopen("div.out","w",stdout); } int main() { // inint(); n=read(),m=read(); for(int i=1;i<=m;i++) a[i]=read(); for(int i=1;i<=m;i++){ for(int j=1;j*j<=a[i];j++){ if(a[i]%j==0){ p[++tot]=j; p[++tot]=a[i]/j; } if(a[i]==j*j)//避免平方数的约数重复计算两次 tot--; } } sort(p+1,p+tot+1); //cout<<"GG"<<endl; //for(int i=1;i<=tot;i++) // cout<<p[i]<<" "; //cout<<endl; int opt=-1,cnt=1; for(int i=1;i<=tot;i++){ if(p[i]<=n){ if(p[i]!=opt){ yzl[cnt]++;//如果前后都不相等,那么都在k=1中 opt=p[i]; cnt=1; //cout<<"yzl[cnt]= "<<yzl[cnt]<<endl; //cout<<"cnt= "<<cnt<<endl; } else { cnt++;//否则往上累加,k=2,3,4…… } } } for(int i=1;i<=m;i++){ sum+=yzl[i]; } //cout<<"sum= "<<sum<<endl; cout<<n-sum<<endl;//先求第一行 for(int i=1;i<=m;i++) cout<<yzl[i]<<endl; return 0; } /* 10 3 4 6 7 5 1 8 */