枚举 + 数论
题意
有一个 \(n*m\;(1<=n,m<=10^6)\) 的矩阵,第 i 行第 j 列是 \(i^j\), 求这个矩阵中的 \(n*m\) 的数中有多少种不同的数
思路
-
第 1 行都是 1;
-
和第 2 行 有可能 重复的只可能在 2 的幂次行;
和第 3 行 有可能 重复的只可能在 3 的幂次行;
第 4 行在 2 的幂次行中;
和第 5 行 有可能 重复的只可能在 5 的幂次行;
和第 6 行 有可能 重复的只可能在 6 的幂次行;
...
-
因此对于每个底数 \(t\), 只要只要知道 \(t\) 最多有 \(k\) 个幂次行,就可以知道当前的底数控制的这些行中有多少不同的数
这个底数 \(t\) 对答案的贡献只与 \(k\) 有关,与 \(t\) 是多少无关(因为底数是一样的,只要指数一样就行)
1 2 3 4 5 2 2^1 2^2 2^3 2^4 2^5 4 2^(2*1) 2^(2*2) 2^(2*3) 2^(2*4) 2^(2*5) 8 2^(3*1) 2^(3*2) 2^(3*3) 2^(3*4) 2^(3*5) -
可以预处理出当某个底数有 \(k\) 个幂次行时,有多少不同的数
//mp[i]表示有当前的底数有i个幂次行时,这i个幂次行在当前底数下,一共有mp[i]个不同的指数 //M = 22 表示即使底数是2,也最多有 20 个幂次行 void presolve() { for (int i = 1; i < M; i++) { for (int j = 1; j <= m; j++) { if (!st[i * j]) { cnt++; st[i * j] = true; } } mp[i] = cnt; } }
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
#define endl "\n"
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10, M = 22;
int n, m;
int mp[M];//mp[i]表示有当前的底数有i个幂次行时,这i个幂次行在当前底数下,一共有mp[i]个不同的指数
int cnt;
bool st[N * M], vis[N];
void presolve()
{
for (int i = 1; i < M; i++)
{
for (int j = 1; j <= m; j++)
{
if (!st[i * j])
{
cnt++;
st[i * j] = true;
}
}
mp[i] = cnt;
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
presolve();
ll ans = 1;
for (int i = 2; i <= n; i++)
{
if (vis[i])
continue;
int j = 0;
ll now = i;
while(now <= n)
{
vis[now] = true;
now *= i;
j++;
}
ans += mp[j];
}
cout << ans << endl;
return 0;
}
标签:774,幂次,Power,int,Codeforces,底数,mp,幂次行,include
From: https://www.cnblogs.com/hzy717zsy/p/16755415.html