E1. Rudolf and Snowflakes (simple version)
题目传送门:
https://codeforces.com/contest/1846/problem/E1
题意:有一个顶点,有k个新顶点与其相连接,可执行无限次以下操作:让最外的每个顶点通过边与k个新顶点相连接(此操作至少做一次),问是否存在k在执行上述操作后,使得顶点总和为n。(数据范围:1e6)
思路:由题意可知,每个图形最初组成至少有1+i+i*i个顶点,1次操作后,会再增加(i*i)*i个顶点,2次操作后,会再增加(i*i*i)*i个顶点......n次操作后会再增加(i*i)*个顶点。由于本题数据较小,可以一次遍历,开一个bool数组,把所有可能的k都枚举一边,再把对应经过相应次数的操作所有的顶点和标记一下,最后再查询n是否被标记即可。
代码显示如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int>PII;
const int N=1e6+10,INF=1e9;
int n;
bool st[N];
void solve()
{
cin>>n;
if(st[n]) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
signed main() {
for(int i=2;i<=1000;i++)
{
int sum=1+i+i*i;//最小雪花所需顶点
int mul=i*i*i;
while(sum<=1000000)
{
st[sum]=true;
sum+=mul;
mul*=i;
}
}
int t;
cin>>t;
while(t--)
{
solve();
}
}
E2. Rudolf and Snowflakes (hard version)
题目传送门:
https://codeforces.com/contest/1846/problem/E2
题意:与E1题意一样,但数据范围不同(1e18)
思路:遍历层数,等比数列求和,二分。
首先按层数遍历,层数最小是三,有题意可知k最小值是2,以2为公比的等比数列的求和公式是(2^x-1)要小于等于1e18,此时这个x代表层数最大值,求得最大层数近似64,所以层数x的范围是3~64。接下来就是求对每个层数对应的顶点总和是否与n相等:
已知等比数列的求和公式是:
x即是对应层数,现在目的就是求k,若直接利用求和公式开根号求解会存在精度问题,所以为了得到准确k就需要进行二分。
代码显示如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int>PII;
const int N = 1e6 + 10, INF = 1e9;
int n, x;
bool st[N];
/*__int128 就是占用128字节的整数存储类型。由于是二进制,范围就是 -2^127~2^127-1,如果使用了 unsigned __int128,则范围变成 00 ~ 21282128,即约39位数,这在一定程度上可以替代高精度运算实现大数运算,而且操作难度更低,
所以在数据范围不超过的情况下,都可以使用__int128。*/
//sum<=(k^n-1)/(k-1)-->k*n>=sum*(k-1)+1
//存在精度问题要用二分
bool check(int x) {
int l = 2, r = 1e9;
while (l <= r) {
int mid = (l + r) / 2;
__int128 po = 1;
__int128 t = (__int128)n * (mid - 1) + 1;
for (int i = 0; i < x; i++) {//若(po==k*n)>(sum*(k-1)+1==t)则不满足,break
po *= mid;
if (po > t) break;
}
//正常情况下要将上个循环循环完整即sum=(k^x-1)/(k-1)则为存在k,返回true
if (po == t) return true;
if (po > t) r = mid - 1;
else l = mid+1;
}
return false;
}
void solve() {
cin >> n;
for (int i = 3; i <= 60; i++) { //遍历层数
if (check(i)) {
cout << "YES" << endl;
return;
}
}
cout << "NO" << endl;
}
signed main() {
int t;
cin >> t;
while (t--) {
solve();
}
}