给出 n , c n,c n,c 让你求出那个函数的值。
举个例子:
n = 6 , c = 3 n=6,c=3 n=6,c=3
f 3 ( 5 ) = m a x { 3 ∗ f 3 ( c d ( 1 , 6 ) ) , 3 ∗ f 3 ( g c d ( 2 , 6 ) ) , 3 ∗ f 3 ( c d ( 3 , 6 ) ) , 3 ∗ f 3 ( c d ( 4 , 6 ) ) , 3 ∗ f 3 ( c d ( 5 , 6 ) ) } f_3(5)=max\{3*f_3(cd(1,6)),3*f_3(gcd(2,6)),3*f_3(cd(3,6)),3*f_3(cd(4,6)),3*f_3(cd(5,6))\} f3(5)=max{3∗f3(cd(1,6)),3∗f3(gcd(2,6)),3∗f3(cd(3,6)),3∗f3(cd(4,6)),3∗f3(cd(5,6))}
= m a x { 3 ∗ f 3 ( 1 ) , 3 ∗ f 3 ( 2 ) , 3 ∗ f 3 ( 3 ) , 3 ∗ f 3 ( 2 ) , 3 ∗ f 3 ( 1 ) } =max\{3*f_3(1),3*f_3(2),3*f_3(3),3*f_3(2),3*f_3(1)\} =max{3∗f3(1),3∗f3(2),3∗f3(3),3∗f3(2),3∗f3(1)}
继续递推下去:
f 3 ( 2 ) = m a x { 3 ∗ f 3 ( g c d ( 1 , 2 ) } f_3(2)=max\{3*f_3(gcd(1,2)\} f3(2)=max{3∗f3(gcd(1,2)}
f 3 ( 3 ) = m a x { 3 ∗ f 3 ( g c d ( 1 , 3 ) , 3 ∗ f 3 ( g c d ( 2 , 3 ) } f_3(3)=max\{3*f_3(gcd(1,3),3*f_3(gcd(2,3)\} f3(3)=max{3∗f3(gcd(1,3),3∗f3(gcd(2,3)}
即:
= m a x { 3 , 3 ∗ 3 , 3 ∗ 3 , 3 ∗ 3 , 3 ∗ 3 } =max\{3,3*3,3*3,3*3,3*3\} =max{3,3∗3,3∗3,3∗3,3∗3}
就是看 c c c 的贡献,也就是 n n n 有多少个质因子可以被分解多少次。
#include
using namespace std;
typedef long long ll;
const int mxn = 1000010, mo = 1000000007;
int p[mxn], lo[mxn], t;
bool vis[mxn];
ll pw(ll a, ll b)
{
ll r = 1;
while (b)
{
if (b & 1)
r = r * a % mo;
a = a * a % mo;
b >>= 1;
}
return r;
}
void shai(int n)
{
t = 0;
vis[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!vis[i])
{
p[++t] = i;
lo[i] = i;
}
for (int j = 1; j <= t && p[j] * i <= n; j++)
{
vis[p[j] * i] = 1;
lo[p[j] * i] = p[j];
if (i % p[j] == 0)
break;
}
}
}
int main()
{
int T, n, c;
shai(1000000);
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &c);
int cnt = 0;
while (n > 1)
{
int x = lo[n];
n /= x;
cnt++;
}
int ans = pw(c, cnt);
printf("%d\n", ans);
}
return 0;
}
给出两条平行线 l 1 l_1 l1 跟 l 2 l_2 l2, l 1 l_1 l1 上有 A 、 B A、B A、B 两点, A A A 在 B B B 的左边, l 2 l_2 l2 上有 C 、 D C、D C、D 两点但 C 、 D C、D C、D 两点的相对位置不知道,给出 A C , A D , B C , B D AC, AD ,BC ,BD AC,AD,BC,BD的长度,判断 C C C 在 D D D 的左还是右边。
分情况讨论就行了。
int main()
{
int t;
sd(t);
while (t--)
{
int ac, ad, bc, bd;
sdd(ac, ad);
sdd(bc, bd);
if (bc == bd)
{
if (ad > ac)
puts("AB//CD");
else
puts("AB//DC");
}
else if (bd > bc)
{
if (ad > ac)
puts("AB//CD");
else
puts("AB//DC");
}
else
{
if (ac > ad)
puts("AB//DC");
else
puts("AB//CD");
}
}
return 0;
}
有 N N N 个苹果,编号为 1 N 1~N 1 N。现要将苹果组成若干对,每对苹果最小公约数不为 1 1 1 。求最多能分成多少对,输出各对的组成。
把 1 − n 1-n 1−n 中的数先预处理里出来他们的最小质因子,把 1 − n 1-n 1−n 所有数的最小质因子存起来,从大到小遍历,是当前质因子倍数个数偶数的直接两两分组,奇数的最小的那个可以判断他的一倍和二倍是否可以匹配,最后看看 2 2 2 的倍数还有多少偶数个没匹配的。
const int N = 5e5 + 50;
int zyz[N], prim[N], cnt = 0, vis[N];
vector<int> v[N];
void init(int n)
{
rep(i, 2, n)
{
if (!zyz[i])
prim[++cnt] = i;
for (int j = i; j <= n; j += i)
if (!zyz[j])
zyz[j] = i;
}
}
void get_pos(int n)
{
rep(i, 1, n)
{
if (zyz[i])
{
int pos = lower_bound(prim + 1, prim + cnt + 1, zyz[i]) - prim; //每个数最小质因子的的位置
v[pos].pb(i);
}
}
}
int main()
{
int t;
sd(t);
init(200010);
while (t--)
{
int n;
sd(n);
rep(i, 1, n)
{
v[i].clear();
vis[i] = 0;
}
get_pos(n);
int pos = upper_bound(prim + 1, prim + cnt + 1, n) - prim;
pos--;
vector<PII> ans;
per(i, pos, 1)
{
if (i == 1)
{
vector<int> res;
res.clear();
for (auto i : v[i])
if (!vis[i])
res.pb(i);
for (int j = 0; j < res.size(); j += 2)
if (j + 1 < res.size())
ans.pb(make_pair(res[j], res[j + 1]));
}
else
{
int len = v[i].size();
if (len % 2 == 0)
{
for (int j = 0; j < len; j += 2)
{
if (j + 1 < len)
ans.pb(make_pair(v[i][j], v[i][j + 1]));
vis[v[i][j]] = 1;
vis[v[i][j + 1]] = 1;
}
}
else
{
for (int j = 1; j < len; j += 2)
{
if (j + 1 < len)
ans.pb(make_pair(v[i][j], v[i][j + 1]));
vis[v[i][j]] = 1;
vis[v[i][j + 1]] = 1;
}
if (2 * v[i][0] <= n)
{
ans.pb(make_pair(v[i][0], 2 * v[i][0]));
vis[v[i][0]] = 1;
vis[2 * v[i][0]] = 1;
}
}
}
}
pd(ans.size());
for (auto i : ans)
pdd(i.fi, i.se);
}
return 0;
}