用户工具

站点工具


2020-2021:teams:manespace:codeforces_round_647_div2

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
2020-2021:teams:manespace:codeforces_round_647_div2 [2020/06/27 17:56]
iuiou
2020-2021:teams:manespace:codeforces_round_647_div2 [2020/06/27 17:58] (当前版本)
iuiou
行 24: 行 24:
  
 题解:原题显然可以转化为选择一些数取正,将另一些数取负,之后加在一起,要和的绝对值最小。首先有个引理:对于上述$p$次幂的集合,将其从大到小排序,若满足$p^{k_1}<​p^{k_2}+p^{k_3}+……+p^{k_n}$,​则必定存在$m$,使得$p^{k_1}=p^{k_2}+p^{k_3}+……+p^{k_m}$,​这是显然的,讲所有数写成p进制,发现这些数最高位全是1,若想从小的加成的大的,必须一位一位的进位,中间总有一种状态为$p^{k_1}$,​这样就很简单了,先将$k$数组从大到小排序,开一个数$now$存目前的值,每当$now$为0就加,否则则减,这样得到的值一定是最小的,注意处理过程中开两个模数去摸,避免倍数差被模数抵消。 题解:原题显然可以转化为选择一些数取正,将另一些数取负,之后加在一起,要和的绝对值最小。首先有个引理:对于上述$p$次幂的集合,将其从大到小排序,若满足$p^{k_1}<​p^{k_2}+p^{k_3}+……+p^{k_n}$,​则必定存在$m$,使得$p^{k_1}=p^{k_2}+p^{k_3}+……+p^{k_m}$,​这是显然的,讲所有数写成p进制,发现这些数最高位全是1,若想从小的加成的大的,必须一位一位的进位,中间总有一种状态为$p^{k_1}$,​这样就很简单了,先将$k$数组从大到小排序,开一个数$now$存目前的值,每当$now$为0就加,否则则减,这样得到的值一定是最小的,注意处理过程中开两个模数去摸,避免倍数差被模数抵消。
 +
 +<​hidden>​
 +<​code>​
 +#include <​bits/​stdc++.h>​
 +using namespace std;
 +typedef long long ll;
 +const int maxn=1e6+13;​
 +int mod1=1e9+7,​mod2=1e9+3;//​这个为了防止去摸的时候产生倍数差 ​
 +int k[maxn];
 +ll qpow(int a,int b,int mod)
 +{
 + int ans=1;
 + int p=a;
 + while(b)
 + {
 + if(b&​1)
 + {
 + ans=1ll*ans*p%mod;​
 + }
 + p=1ll*p*p%mod;​
 + b>>​=1;​
 + }
 + return 1ll*ans;
 + }
 +int main()
 +{
 + int t;
 + scanf("​%d",&​t);​
 + while(t--)
 + {
 + ll ans1=0,​ans2=0;​
 + int n,p;
 + scanf("​%d%d",&​n,&​p);​
 + for(int i=1;​i<​=n;​i++)
 + {
 + scanf("​%d",&​k[i]);​
 + }
 + sort(k+1,​k+1+n);​
 + for(int i=n;i;i--)
 + {
 + if(!ans1&&​!ans2)
 + {
 + ans1+=qpow(p,​k[i],​mod1);​
 + ans2+=qpow(p,​k[i],​mod2);​
 + }
 + else
 + {
 + ans1-=qpow(p,​k[i],​mod1);​
 + ans1=(ans1%mod1+mod1)%mod1;​
 + ans2-=qpow(p,​k[i],​mod2);​
 +     ans2=(ans2%mod2+mod2)%mod2;​
 + }
 + }
 + printf("​%lld\n",​ans1);​
 + }
 + ​} ​
 +</​code>​
 +</​hidden>​
  
  
  
2020-2021/teams/manespace/codeforces_round_647_div2.1593251788.txt.gz · 最后更改: 2020/06/27 17:56 由 iuiou