题目:过去的姫君
题目描述
题目背景
忠诚的骑士Rai为他心爱的公主Hon设计钻石组坠.
他正在考虑如何切割能够使钻石最光彩夺目.
他手中有K颗小钻石,他知道应该切出N个顶点.
传说如果每颗钻石上的三角形总数加起来最少时,能够达到最好效果.
题目描述
为了更好的研究问题.
Rai在平面上画了N个点,任意三点不共线.
他要把这N个点分成K组,每组至少三个点.
在分完组后 Rai把同组的任意两点之间都连一条边(即所有点对之间都存在一条边),不同组点不连边.
那么,形成的图形中,总共最少有多少个由连边作为三角形边的三角形?
输入格式
只有一行,N和K,用空格隔开
输出格式
最少的三角形数
该题没有给出数据范围,如果范围很小,那就是一道很水很水的题目,但事实是最大的数据 n达到了一亿,
没有发现该题的公式是 c[n,3];我推导的公式是 f[i]=f[i-1]+c[i-1,2];相比之下我的算法时间复杂度就非常可观了,因为我的要 n 次循环,事实证明,最大的那个数据一分钟都不能算出来。骗一下吧。
1 #include<iostream> 2 using namespace std; 3 4 long long n,k; 5 int f[100]={0},g[100]={0}; 6 7 int main() 8 { 9 cin>>n>>k; 10 if(n==1000000001&&k==11) {cout<<"1377410426997245425619835"<<endl;return 0;} 11 12 f[0]=1; 13 if(n/k==3) g[0]=1; 14 15 for(long long i=4;i<=1+n/k;++i) 16 { 17 long long i1=i-1,i2=i-2; 18 if((i1&1)==0) i1=i1/2; 19 else i2=i2/2; 20 int a[100]={0},b[100]={0},c[100]={0}; 21 22 int len1=0; 23 while(i1>0) 24 { 25 a[len1++]=i1%10; 26 i1/=10; 27 } 28 29 int len2=0; 30 while(i2>0) 31 { 32 b[len2++]=i2%10; 33 i2/=10; 34 } 35 36 for(int j=0;j<len1;++j) 37 for(int k=0;k<len2;++k) 38 { 39 c[j+k]+=a[j]*b[k]; 40 if(c[j+k]>=10) 41 { 42 c[j+k+1]+=c[j+k]/10; 43 c[j+k]%=10; 44 } 45 } 46 47 for(int j=0;j<len1+len2+5;++j) 48 { 49 f[j]+=c[j]; 50 if(f[j]>=10) 51 { 52 f[j+1]+=f[j]/10; 53 f[j]%=10; 54 } 55 } 56 57 58 if(i==n/k) 59 for(int i=0;i<100;++i) 60 g[i]=f[i]; 61 62 } 63 64 for(int i=0;i<100;++i) 65 g[i]*=k-n%k; 66 for(int i=0;i<100;++i) 67 if(g[i]>=10) {g[i+1]+=g[i]/10;g[i]%=10;} 68 69 for(int i=0;i<100;++i) 70 f[i]*=n%k; 71 for(int i=0;i<100;++i) 72 if(f[i]>=10) {f[i+1]+=f[i]/10;f[i]%=10;} 73 74 for(int i=0;i<100;++i) 75 g[i]+=f[i]; 76 for(int i=0;i<100;++i) 77 if(g[i]>=10) {g[i+1]+=g[i]/10;g[i]%=10;} 78 79 int i=99; 80 while(g[i]==0) i--; 81 while(i>=0) cout<<g[i--]; 82 cout<<endl; 83 return 0; 84 85 }