CodeForces 1081E Missing Numbers <<数学

题意

有一个前缀和是平方数的序列,也就是一个严格递增平方数的差分序列,奇数项丢了,给出偶数项,要求输出所有项。

思路

首先列出一个式子,对于题设差分序列中的一项c,必定要满足有$a^2-b^2=c$,即$(a-b)\times(a+b)=c$,那么现在已知c,如何定出a和b呢,很容易想到把c因式分解,使$(a-b)$,$(a+b)$为c的一对因子即可。设其中一个因子为x,不妨设x为一对之中大的那个因子,那么令$a+b=x$,$a-b=c/x$联立两式可解得,$2a=x+c/x$,$2b=x-c/x$。那么a,b存在的充分必要条件就是这对因子和(差)为偶数即可,换言之,一对和(差)为偶数的因子即可构造出c,且其他所有的数都不能构造出c(不会证明,可能是错的)。

推进到这里,我们就可以开始构造题目要求的序列了。针对每个数,我们都选择构造尽量小的平方数,这样保证在之后的构造中能够有更多的选择。在构造当前数的选择上,已经有的前缀和为now,那么当前数就为$b^2-now^2$。

进行上述步骤,哪步进行不下去就No。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+7;
 4 int arr[maxn];
 5 vector<int> fac[maxn];
 6 long long ans[maxn];
 7 int main()
 8 {
 9     int n;
10     scanf("%d",&n);
11     n/=2;
12     for(int i=0;i<n;i++)
13     {
14         scanf("%d",&arr[i]);
15         for(int j=1;j<sqrt(arr[i]);j++)
16         {
17             if(arr[i]%j==0)
18                 fac[i].push_back(arr[i]/j);
19         }
20         sort(fac[i].begin(),fac[i].end());
21     }
22     int now=0;
23     bool flag=1;
24     for(int i=0;i<n;i++)
25     {
26         for(int j=0;j<fac[i].size();j++)
27         {
28             int a=fac[i][j],b=arr[i]/a;
29             if((a+b)%2) continue;
30             int aa=(a+b)/2,bb=(a-b)/2;
31             if(bb<=now) continue;
32             else{
33                 ans[i]=1LL*bb*bb-1LL*now*now;
34                 now=aa;
35                 break;
36             }
37         }
38         if(ans[i]==0) flag=0;
39         if(!flag) break;
40     }
41     if(!flag) puts("No");
42     else {
43         puts("Yes");
44         for(int i=0;i<n;i++)
45         {
46             printf("%lld %d ",ans[i],arr[i]);
47         }
48     }
49 
50 }

后记

推公式真好玩。

posted @ 2018-12-17 17:51  computer_luo  阅读(298)  评论(0编辑  收藏  举报