Divisors


【胡诌】

  这道题Claris已经写了题解了,我再写是为了加深理解

【30%

  这个很容易想,暴力嘛

  枚举1到n所有的数,对于each i∈[1,n],检验它是否是a[1]...a[m]的约数,如果是,计数器++

  这样就统计出了[1,n]内每个数是几个数的约数,然后在统计一下对于[1,m]每个k,cnt[i]=k的有多少个,输出就行了

【40%~60%】

  这几个点,只有一个数a[1],当k=1时就是要你统计“有多少个数是1个数的约数”,那既然m=1,所以这“一个数”就是a[1]。就是“有多少个数是a[1]的约数”,也就是“a[1]”有多少约数,当然别忘了是在区间[1,n]中。

  那你就直接在sqrt(a)的时间内统计它的约数个数就是了。k=0时的答案就是n-(k=1时的答案)

  复杂度O(√a)

【100%】

  这个当时没想出来。。。其实现在看来当时挺近了

  先不考虑k=0的情况

  当k>=1时,只有a[1]...a[m]的约数(当然是各自的约数的并集)才会对答案有所贡献,所以对a[1]...a[m]统计各自的所有因数,然后放到一个map里,看看每个因数出现了多少次,在像上面那样做一下统计就行了。对于k=0的情况,用n减去map的大小就行了。

  时间复杂度O( m*sqrt(a)*log2( sqrt(a) ) ) 其中的那个log是使用map算上的

【评测结果】


【代码】

#include <cstdio>
#include <cmath>
#include <map>
using namespace std;
int a[210], n, m, cnt[210];
map<int,int> table;
void push(int x)
{
	map<int,int>::iterator it;
	it=table.find(x);
	if(it==table.end())table[x]=1;
	else it->second++;
}
int main()
{
	int i, j, t;
	map<int,int>::iterator it;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)scanf("%d",a+i);
	for(i=1;i<=m;i++)
	{
		t=(int)sqrt(a[i]);
		for(j=1;j<=t;j++)
			if(a[i]%j==0)
			{
				if(j<=n)push(j);
				if(a[i]/j<=n and j!=a[i]/j)push(a[i]/j);
			}
	}
	for(it=table.begin();it!=table.end();it++)cnt[it->second]++;
	printf("%d\n",n-table.size());
	for(i=1;i<=m;i++)printf("%d\n",cnt[i]);
	return 0;
}


// 就是用6阶taylor展开算e^x,是一个的单元,和个数无关,并行算指数。 module exponent (x,clk,enable,output_exp,ack); parameter DATA_WIDTH=32; localparam taylor_iter=7; input [DATA_WIDTH-1:0] x; input clk; input enable; output reg ack; output reg [DATA_WIDTH-1:0] output_exp; reg [DATA_WIDTH*taylor_iter-1:0] divisors; // 1/6 1/5 1/4 1/3 1/2 1 1 reg [DATA_WIDTH-1:0] mult1; //is 1 in the first cycle and then the output of the second multiplication in the rest reg [DATA_WIDTH-1:0] one_or_x; //one in the first cycle and then x for the rest wire [DATA_WIDTH-1:0] out_m1; //output of the first multiplication which is either with 1 or x wire [DATA_WIDTH-1:0] out_m2; //the output of the second muliplication and the input of the first wire [DATA_WIDTH-1:0] output_add1; reg [DATA_WIDTH-1:0] out_reg; //the output of the Addition each cycle // reg enable_r; floatMult FM1 (mult1,one_or_x,out_m1); floatMult FM2 (out_m1,divisors[31:0],out_m2); floatAdd FADD1 (out_m2,out_reg,output_add1); always @ (posedge clk) begin // enable_r<=enable; if(enable==1'b0) begin one_or_x=32'b00111111100000000000000000000000; //initially 1 mult1=32'b00111111100000000000000000000000; //initially 1 out_reg=32'b00000000000000000000000000000000; //initially 0 output_exp=32'b00000000000000000000000000000000; //output zero until ack is 1 divisors=224'b00111110001010101010101010101011_00111110010011001100110011001101_00111110100000000000000000000000_00111110101010101010101010101011_00111111000000000000000000000000_00111111100000000000000000000000_00111111100000000000000000000000; ack=1'b0; // acknowledge is 0 at the beginning end else begin one_or_x=x; mult1=out_m2; //get the output of the second multiplication to multiply with x divisors=divisors>>32; //shift 32 bit to divide the out_m1 with the new number to compute the factorial out_reg=output_add1; if(divisors==224'b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) begin output_exp=output_add1; ack=1'b1; end end end endmodule 这段代码里ack为1后是一直保持吗
最新发布
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值