二分高精度Vijos P1472 教主的集合序列

Posted Coolxxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分高精度Vijos P1472 教主的集合序列相关的知识,希望对你有一定的参考价值。

 题目链接:

  https://vijos.org/p/1472

题目大意

  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 教主的集合序列的主要内容,如果未能解决你的问题,请参考以下文章

Vijos 包裹快递(二分)

Vijos1450 包裹快递[二分答案]

vijos P1375 大整数(高精不熟的一定要做!)

Vijos 1470 教主的后花园

LCIS(最长公共上升子序列)Vijos1264神秘的咒语

[Vijos1617] 超级教主(DP + 单调队列)