二分高精度Vijos P1472 教主的集合序列
Posted Coolxxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分高精度Vijos P1472 教主的集合序列相关的知识,希望对你有一定的参考价值。
题目链接:
题目大意:
S1={1,2,3…n}。当i>1时,Si为集合Si-1中任意两个不相同数之和的集合。
将每个集合中所有元素取出,集合Si的数放在集合Si+1的数的前面,同一个集合数从小到大排序,这样得到一个序列L。
题目输入n和K,求L中第K个数是多少。
变态的数据范围:K≤101000,1<n≤1000;且数据保证当n≤3时,K≤900000。
题目思路:
【二分】【高精度】
真是恶心的一道题啊。。打了好久。
S1={1,2,...,n}
S2={3,4,...,2n-1}
S3={7,8,...,4n-3}
S4={15,16,...,8n-7}
S5={31,32,...,16n-15}
......
Sk={2k-1,2k,...,n*2k-1-2k-1+1}={2k-1,2k,...,(n-1)2k-1+1}
所以第k个集合的大小为(n-1)*2k-1-2k+3
前k个集合总数为(n-3)*2k+3(k+1)-n
二分目标数处在第几个集合,然后简单运算并输出即可。注意n=1,2,3的情况。
1 // 2 //by coolxxx 3 // 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<memory.h> 9 #include<time.h> 10 #include<stdio.h> 11 #include<stdlib.h> 12 #include<string.h> 13 #include<stdbool.h> 14 #include<math.h> 15 #define min(a,b) ((a)<(b)?(a):(b)) 16 #define max(a,b) ((a)>(b)?(a):(b)) 17 #define abs(a) ((a)>0?(a):(-(a))) 18 #define lowbit(a) (a&(-a)) 19 #define sqr(a) ((a)*(a)) 20 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) 21 #define eps 1e-8 22 #define J 10000000 23 #define MAX 0x7f7f7f7f 24 #define PI 3.1415926535897 25 #define N 1007 26 #define M 10007 27 using namespace std; 28 typedef long long LL; 29 int cas,cass; 30 int n,m,lll,ans; 31 LL k[M]; 32 char ch[N]; 33 void gjdprint(LL a[]) 34 { 35 int i; 36 printf("%lld",a[a[0]]); 37 for(i=a[0]-1;i;i--) 38 printf("%07lld",a[i]); 39 puts(""); 40 } 41 int gjdcompare(LL a[],LL b[])//-1:a=b 0:a<b 1:a>b 42 { 43 int i; 44 if(a[0]!=b[0])return a[0]>b[0]; 45 for(i=a[0];i;i--) 46 if(a[i]!=b[i])return a[i]>b[i]; 47 return -1; 48 } 49 void gjdcheng(LL a[],LL b[],LL c[]) 50 { 51 LL t[M]={0}; 52 int i,j; 53 t[0]=a[0]+b[0]; 54 for(i=1;i<=a[0];i++) 55 for(j=1;j<=b[0];j++) 56 t[i+j-1]+=a[i]*b[j]; 57 for(i=1;i<=t[0];i++) 58 t[i+1]+=t[i]/J,t[i]%=J; 59 while(t[t[0]+1])t[0]++; 60 while(!t[t[0]] && t[0]>1)t[0]--; 61 memcpy(c,t,sizeof(t)); 62 } 63 void gjdquickpow(LL a[],LL x) 64 { 65 LL t[M]={1,2,0}; 66 a[0]=a[1]=1; 67 while(x) 68 { 69 if(x&1) 70 { 71 gjdcheng(a,t,a); 72 } 73 gjdcheng(t,t,t); 74 x>>=1; 75 } 76 } 77 void gjdchange(char s[],LL a[]) 78 { 79 int i,j,l; 80 l=strlen(s); 81 for(i=l,a[0]=1;i>6;i-=7,a[0]++) 82 { 83 for(j=0;j<7;j++) 84 a[a[0]]=a[a[0]]*10+s[i-7+j]-\'0\'; 85 } 86 for(j=0;j<i;j++) 87 a[a[0]]=a[a[0]]*10+s[j]-\'0\'; 88 } 89 void gjdjia(LL a[],LL b[],LL c[]) 90 { 91 int i; 92 LL t[M]={0}; 93 t[0]=max(a[0],b[0]); 94 for(i=1;i<=t[0];i++) 95 t[i]=a[i]+b[i]; 96 for(i=1;i<=t[0];i++) 97 t[i+1]+=t[i]/J,t[i]%=J; 98 while(t[t[0]+1])t[0]++; 99 while(!t[t[0]] && t[0]>1)t[0]--; 100 memcpy(c,t,sizeof(t)); 101 } 102 void gjdjian(LL a[],LL b[],LL c[]) 103 { 104 int i; 105 LL t[M]={0}; 106 t[0]=a[0]; 107 for(i=1;i<=t[0];i++) 108 t[i]=a[i]-b[i]; 109 for(i=1;i<t[0];i++) 110 if(t[i]<0)t[i+1]--,t[i]+=J; 111 while(!t[t[0]] && t[0]>1)t[0]--; 112 memcpy(c,t,sizeof(t)); 113 } 114 void gjdchu2(LL a[]) 115 { 116 int i; 117 for(i=a[0];i>1;i--) 118 { 119 if(a[i]&1)a[i-1]+=J; 120 a[i]>>=1; 121 } 122 a[1]>>=1; 123 while(!a[a[0]] && a[0]>1)a[0]--; 124 } 125 void getsum(LL t[],LL mid,LL tt[]) 126 { 127 gjdquickpow(t,mid-1); 128 tt[1]=n-3; 129 gjdcheng(t,tt,t); 130 tt[1]=mid*3; 131 gjdjia(t,tt,t); 132 tt[1]=n; 133 gjdjian(t,tt,t); 134 } 135 void work() 136 { 137 int i,j,l,r,mid; 138 LL t[M]={0},tt[M]={1,0}; 139 l=1;r=4000; 140 while(l<r) 141 { 142 mid=(l+r+1)>>1; 143 getsum(t,mid,tt); 144 j=gjdcompare(k,t); 145 if(j==-1) 146 { 147 gjdquickpow(t,mid-2); 148 tt[1]=n-1; 149 gjdcheng(t,tt,t); 150 tt[1]=1; 151 gjdjia(t,tt,t); 152 gjdprint(t); 153 return; 154 } 155 if(j)l=mid; 156 else r=mid-1; 157 } 158 getsum(t,r,tt); 159 gjdjian(k,t,k); 160 gjdquickpow(t,r); 161 tt[1]=2; 162 gjdjian(t,tt,t); 163 gjdjia(k,t,t); 164 gjdprint(t); 165 } 166 int main() 167 { 168 #ifndef ONLINE_JUDGE 169 // freopen("1.txt","r",stdin); 170 // freopen("2.txt","w",stdout); 171 #endif 172 int i,j; 173 // while(~scanf("%s",s1)) 174 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 175 while(~scanf("%d",&n)) 176 { 177 memset(k,0,sizeof(k)); 178 if(n<4) 179 { 180 scanf("%d",&m); 181 if(n==1) 182 { 183 if(m==1)puts("1"); 184 else puts("-1"); 185 } 186 else if(n==2) 187 { 188 if(m==1)puts("1"); 189 else if(m==2)puts("2"); 190 else if(m==3)puts("3"); 191 else puts("-1"); 192 } 193 else if(n==3) 194 { 195 gjdquickpow(k,(m+2)/3); 196 if(m%3==1)k[1]--; 197 else if(m%3==0)k[1]++; 198 gjdprint(k); 199 } 200 continue; 201 } 202 scanf("%s",ch); 203 gjdchange(ch,k); 204 if(k[0]==1 && k[1]<=n) 205 { 206 gjdprint(k); 207 continue; 208 } 209 work(); 210 } 211 return 0; 212 } 213 214 /* 215 // 216 217 // 218 */
以上是关于二分高精度Vijos P1472 教主的集合序列的主要内容,如果未能解决你的问题,请参考以下文章