Good Bye 2018 C. New Year and the Sphere Transmission

传送门

https://www.cnblogs.com/violet-acmer/p/10201535.html

题意

  $n$ 个 $people$,编号 $1,2,3,\cdots ,n$ ,按顺时针方向围城一圈;

  初始,编号为 $1$ 的 $people$ 抱着一个球,他可以将球顺时针传给他左手边的第 $k$ 个 $people$;

  接到球的 $people$ 依次将球传给他顺时针方向的第 $k$ 个 $people$;

  循环进行,直到球再一次落到 $1$ 号 $people$ 手中,结束;

  定义一个开心值 :所有接到球的 $people$ 的编号和。

  求所有的开心值,并按升序排列。

题解

  弱弱的我只能通过打表找规律%%%%%%%那些一眼看出规律的大神们 

  $\begin{aligned} k &= 1\rightarrow 1 \\ k&= 2\rightarrow 1,3 \\ k&= 3\rightarrow 1,6 \\ k&= 4\rightarrow 1,4,10 \\ k&= 5\rightarrow 1,15 \\ k&= 6\rightarrow 1,5,9,21 \\ k&= 7\rightarrow 1,28\end{aligned}$

  刚开始,发现,有些数的开心值只有两个,然后,把这些只有两个开心值的数列了一下,发现,全是素数。

  不知为啥,求了一下每个数的因子个数,发现没,开心值的个数与他们的因子个数有关!!!

  然后,在草纸上列出了前 12 项的答案,找了一下规律,哇,最后10分钟,找到了一个前10个通用的规律。

  最后结束时刻提交,emmmmm,wa

  然后,睡觉,哈哈哈。

  今天,把昨天的错误数据看了一下,重新找了一下规律

  emmmm,找到了

  以 $k=15$ 为例:

    $15$ 的因子为 $1,3,5,15$

    开心值为 $1,18,35,120$

    1=1;

    18=1+6+11;                    //d=5,tot=3

    35=1+4+7+10+13;                   //d=3,tot=5

    120=1+2+3+4+5+6+7+8+9+10+11+12+13+14+15;         //d=1,tot=15

  发现没,开心值就是以 $15$ 的因子为公差的前 $tot$ 项和;

•Code

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define ll __int64
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e6+; ll n;
ll a[maxn];
ll res[maxn]; int factor()//求出n的所有因子
{
int x=sqrt(n);
a[]=;
int index=;
for(int i=;i <= x;++i)
{
if(n%i == )
{
a[++index]=i;
if(n/i != i)
a[++index]=n/i;
}
}
a[++index]=n;
return index;
}
int main()
{
scanf("%d",&n);
int t=factor();
sort(a+,a+t+);
for(int i=;i <= t;++i)
{
ll d=a[i],tot=n/d;
ll a1=,an=a1+(tot-)*d;
res[i]=tot*(a1+an)/;
}
for(int i=t;i >= ;--i)
printf("%I64d ",res[i]);
}

•打表找规律代码

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll __int64
#define mem(a,b) memset(a,b,sizeof(a))
const ll MOD=;
const int maxn=1e6+; int n;
int a[maxn]; int main()
{
for(int i=;i <= ;++i)
{
i=;
int tot=;
for(int k=;k <= i;++k)
{
int res=;
int index=+k;
printf("****\nk=%d\n",k);
printf("");
while(index != )
{
if(index > i)
index %= i;
if(index == )
break;
res += index;
printf("+%d",index);
index += k;
}
printf("=%d\n",res);
a[tot++]=res;
} sort(a,a+tot);
int t=unique(a,a+tot)-a;
printf("\n===========\ni=%d\n",i);
for(int j=;j < t;++j)
printf("%d ",a[j]);
break;
}
}
//1 27 105 235 625 1275

分割线2019.6.14

感悟

  因打表找规律而AC的题,不能当作正解,赛后补题,要花时间思考正解;

•想法

  从编号为 $1$ 的 $people$ 开始传球,依次传给其顺时针方向的第 $k$ 个人;

  可以肯定的是,球一定会回到 $1$ 手中,假设传了 $x$ 次,球重新回到 $1$ 手中;

  并假设这 $x$ 次传球,共传了 $y$ 轮,如下图所示:

  Good Bye 2018 C. New Year and the Sphere Transmission

第 i 轮对应的序列 $(i-1)\cdot n+1,(i-1)\cdot n+2,\cdots ,i\cdot n$ 对应的 $people$ 编号为 $1,2,\cdots ,n$;

  也就是 $1+x\cdot k = 1+y\cdot n$,即 $x\cdot k = y\cdot n$;

  我们来分析一下这个等式可以推出什么神奇的东西:

  Good Bye 2018 C. New Year and the Sphere Transmission

  为什么要最小的 $x$ 呢?

  因为只要传球期间来到 $1$ 就停止,所以需要的是最小的 $x$;

  如果 $GCD(k,n) = k$,那么传一轮便可以来到 $1$ 处;

  如果 $GCD(k,n) \neq k$,那么需要传多轮才能来到 $1$ 处;

  那么下面来讨论 $GCD(k,n) \neq k$  的情况;

  假设 $GCD(k,n) = f$,这种情况下共传球 $x=\frac{n}{f}$ 次,与 $k=f$ 的传球次数相同;

  又因为 $f\ |\ k$,所以,这 $x$ 次传球的 $people$ 的编号一定相同;

  所以,对于任意 $k$,传球次数和编号只与 $GCD(n,k)$ 有关系;

  也就是只和 $n$ 的因子有关系;

  当 $GCD(n,k) = f$ 时,接到球的 $people$ 编号为:

    $1\rightarrow (1+f)\rightarrow (1+2f) \rightarrow \cdots \rightarrow (1+xf)$;

  共传球 $x=\frac{n}{f}$ 次;

  满足首项 $a_1=1$,末项 $a_{x+1}=n+1$,公差 $d=f$ 的等差数列;

  前 $x$ 项和即为当前的开心值;

•Code

 #include<bits/stdc++.h>
using namespace std;
#define ll long long int n;
vector<int >f;
vector<ll >ans; void Factor(int n)///求解 n 的因子
{
f.clear();
for(int i=;i*i <= n;++i)
{
if(n%i != )
continue; f.push_back(i);
if(n/i != i)
f.push_back(n/i);
}
}
void Solve()
{
Factor(n); for(int i=;i < f.size();++i)
{
ll d=f[i];
ll x=n/f[i];
ll s=x*(++(x-)*d)/;
ans.push_back(s);
}
sort(ans.begin(),ans.end());
for(int i=;i < ans.size();++i)
printf("%lld ",ans[i]);
}
int main()
{
scanf("%d",&n);
Solve(); return ;
}

应用

•题目描述

Good Bye 2018 C. New Year and the Sphere Transmission

•题解

  使得所有人都拿过球,类比于上题,也就是说求使得开心值为 $1+2+3+\cdots +n$ 的最大的 $k$;

  那么,只有当 $GCD(n,k)=1$ 时,球才会传递给 $x=n$ 个人;

  那么,本题就转化为求解 $GCD(n,k) = 1$ 的,并且满足 $k \le n$ 的最大的 $k$;

  显然,$k=n-1$ 为满足条件的最大的 $k$;

•变形

  如果限制 $k \le \frac{n}{2}$ 呢?

•分析

  如果 $n$ 为奇数,那么 $\lfloor{ \frac{n}{2} }\rfloor$ 一定与 $n$ 互素;

  如果 $n$ 为偶数,那么,如果 $\frac{n}{2}$ 为奇数,答案为 $\frac{n}{2}-2$;

  反之,如果 $\frac{n}{2}$ 为偶数,那么答案为 $\frac{n}{2}-1$,因为奇数与偶数一定互素;

  也就是说,直接判断 $\lfloor{ \frac{n}{2} }\rfloor\ ,\ \lfloor{ \frac{n}{2} }\rfloor-1\ ,\ \lfloor{ \frac{n}{2} }\rfloor-2$ 这三个数哪个与 $n$ 互素即可;

上一篇:linux的shadow文件


下一篇:Good Bye 2018 A. New Year and the Christmas Ornament