TYVJ P1651

背景 Background

清北学堂杯Tyvj2周年邀请赛 第三道

描述 Description

VNB从小立志当一名杰出的数学家。有一天,admin给了VNB一个任务:求int(√1)+int(√2)+……+int(√n)的值是多少。VNB 以为很简单,就接下了这个任务,但是当他看到n的范围大小就傻眼了。所以,他打着“节约计算用纸以保护地球”的口号向你发出了求救。
注: int(x)表示实数x的整数部分。
再注:VNB怕你算太长时间,就先帮你算出了int(√n)的大小,来帮助你更好的完成此题。

输入格式 InputFormat

共两行每行一个正整数
分别为N和 K,K表示int(√n)

输出格式 OutputFormat

仅一行一个正整数,为int(√1)+int(√2)+……+int(√n)的值。

样例输入 SampleInput [复制数据]

10
3

样例输出 SampleOutput [复制数据]

19

数据范围和注释 Hint

30%的数据k<=2*10^6(保证结果在int64 or comp以内)
90%的数据k<=10^100
所有的数据保证k<=10^10000  k^2<=n<(k+1)^2

思路:这道题是我两年前用pascal写过的最长的一道题了,,但是当时还不会压位,最后一个点还T了,现在好多了,通项公式:ans=(6*k*n-2*k*k*k-3*k*k+5k)/6;

#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

typedef long long ll;
const int maxn=4020,maxl=4000,ml=4010;
const ll mod=100000000;
ll a[ml],b[ml],c[ml],kn6[ml],six[ml],k[ml],n[ml],k2[ml];
ll ans[ml],kkk2[ml],kk3[ml],k5[ml],five[ml];
ll two[ml],three[ml];
ll t,add;
int h;
char kk[maxn*10],nn[maxn*10];

void close()
{
exit(0);
}

void mul(ll *a,ll *b,ll *c)
{
	int reach;
	for (reach=0;a[reach]==0 && reach<=maxl;reach++);
	for (int i=maxl;i>=reach;i--)
	{
		h=i;
		for (int j=maxl;j>=1;j--)
		{
			if (h==1) break;
			t=a[i]*b[j];
			c[h]+=t;
			c[h-1]+=c[h] / mod;
			c[h] %= mod;
			h--;
		}
	}
}

void muls(ll *a,int v)
{
	add=0;
	for (int i=maxl;i>=1;i--)
	{
		t=add+a[i]*v;
		a[i]=t % mod;
		add=t / mod;
	}
}

void plus(ll *a,ll *b,ll *c)
{
	add=0;
	for (int i=maxl;i>=1;i--)
	{
		t=a[i]+b[i]+add;
		c[i]=t % mod;
		add=t / mod;
	}
}

void sub(ll *a,ll *b,ll *c)
{
	add=0;
	for (int i=maxl;i>=1;i--)
	{
		t=a[i]-b[i];
		if (t<0)
		{
			a[i-1]--;
			t+=mod;
		}
		c[i]=t;
	}
}

void divide(int div,ll *a,ll *b)
{
	t=0;add=0;
	for (int i=1;i<=maxl;i++)
	{
		t=add * mod+a[i];
		b[i]=t / div;
		add=t % div;
	}
}

void print(ll *a)
{
	int i;
	for (i=0;i<maxl && a[i]==0;i++);
	printf("%lld",a[i]);
	if (i==maxl) printf("
");
	for (int j=i+1;j<=maxl;j++)
	{
		printf("%08lld",a[j]);
		if (j==maxl)
			printf("
");
	}
}

void work()
{
	mul(k,n,kn6);
	muls(kn6,6);
	/////////////////////
	mul(k,k,kk3);
	mul(kk3,k,kkk2);
	muls(kkk2,2);
	////////////////////
	memset(a,0,sizeof(a));
	muls(kk3,3);
	////////////////////////
	memcpy(k5,k,sizeof(k));
	muls(k5,5);
	/////////////////////
	plus(kn6,k5,ans);
	sub(ans,kkk2,ans);
	sub(ans,kk3,ans);
	divide(6,ans,ans);
	print(ans);
	/*
	mul(k,n,kn6);
	memset(six,0,sizeof(six));
	six[maxl]=6;
	mul(kn6,six,kn6);
	print(kn6);
	close();
	//--------------------------
	mul(k,k,kkk2);//k*k->kkk
	mul(kkk2,k,kkk2);//k*k*k->kkk
	two[maxl]=2;
	mul(kkk2,two,kkk2);//2*k*k*k->kkk
	//--------------------------
	mul(k,k,kk3);//k*k->kk3
	three[maxl]=3;
	mul(kk3,three,kk3);//k*k*3->kk3
	//-------------------------------
	memset(five,0,sizeof(five));
	five[maxl]=5;
	mul(k,five,k5);//k*5->k5
	//-------------------------------
	plus(kn6,k5,ans);
	sub(ans,kkk2,ans);
	sub(ans,kk3,ans);
	divide(6,ans,ans);
	print(ans);
	printf("Real Answer:%d
",(6*kk*nn-kk*kk*kk*2-kk*kk*3+5*kk)/6);
	printf("kn6:%d
",6*kk*nn);
	printf("kkk2:%d
",kk*kk*kk*2);
	printf("kk3:%d
",kk*kk*3);
	printf("k5:%d
",kk*5);
	printf("1 step:%d
",6*kk*nn+kk*5);
	printf("%d
",6*kk*nn+kk*5-kk*kk*kk*2);
	printf("%d
",6*kk*nn+kk*5-kk*kk*kk*2-kk*kk*3);
	*/
}

void convert(char *s,ll *b)
{
	int l=strlen(s),rec=0;
	h=maxl;
	t=1;add=0;
	for (int i=l-1;i>=0;i--)
	{
		rec++;
		add+=t*(s[i]-'0');
		t*=10;
		if (rec==8)
		{
			rec=0;
			b[h]=add;
			add=0;
			t=1;
			h--;
		}
	}
	if (add!=0)	b[h]=add;
}


void init()
{
	scanf("%s %s",nn,kk);
	convert(nn,n);
	convert(kk,k);
	work();
}

int main ()
{
	init();
	close();
	return 0;
}
原文地址:https://www.cnblogs.com/cssystem/p/3170643.html