B、Basic Gcd Problem
此题wa了16次,恶心的我不行
可以发现当前f[x] 肯定是c的幂次,那么就看x最大时c的多少幂次了。再看x和i的gcd,也就相当于x的约数
从上面看出规律,x如果要是最大,会从它的约数里面挑出最大的y,那么这个y也想最大,所以他也会从它的约数里面挑出z
[x = k * y = k * (p * z)
]
所以也就是最长的上升的,任意两个数都是倍数关系的序列例如1,2,4,8,32,但是发现,这个不需要可以的去求最长了,最长的个数时固定的,贪心来讲,当前x到下面一个y,y = k * x,那么这个k应该最小,最小应该是什么呢,质数,一个质因子,那么在这个上升子序列里面所有k[i] , 满足y[i] = k[i] * x[i] , 并且肯定每个k都是质因子,长度也就等于n的质因子个数(可以枚举几个数试试)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <map>
#include <list>
#include <queue>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <stack>
#include <set>
#pragma GCC optimize(3 , "Ofast" , "inline")
using namespace std ;
#define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
#define x first
#define y second
typedef long long ll ;
const double esp = 1e-6 , pi = acos(-1) ;
typedef pair<int , int> PII ;
const int N = 1e6 + 10 , INF = 0x3f3f3f3f , mod = 1e9 + 7;
ll in()
{
ll x = 0 , f = 1 ;
char ch = getchar() ;
while(!isdigit(ch)) {if(ch == '-') f = -1 ; ch = getchar() ;}
while(isdigit(ch)) x = x * 10 + ch - 48 , ch = getchar() ;
return x * f ;
}
ll qmi(ll a , ll b){
ll res = 1 ;
while(b) {
if(b & 1) res = res * a % mod ;
a = a * a % mod ;
b >>= 1 ;
}
return res ;
}
void work(){
int n , c ;
scanf("%d%d" , &n , &c) ;
int ans = 0 ;
for(int i = 2; i <= n / i ;i ++)
while(n % i == 0) n /= i , ans ++ ;
if(n > 1) ans ++ ;
printf("%d
" , qmi(c , ans) % mod) ;
return ;
}
int main()
{
int t = in() ;
while(t --) work() ;
return 0 ;
}
/*
*/
F、Finding the Order
高手:两个三角形符合两边之和大于第三边,那么两个组合起来就是两个内边加起来大于两个外边
#include<bits/stdc++.h>
using namespace std;
int t,ac,ad,bc,bd;
int main(){
cin>>t;
while(t--){
cin>>ac>>ad>>bc>>bd;
if(ac+bd<ad+bc)cout<<"AB//CD"<<endl;else cout<<"AB//DC"<<endl;
}
return 0;
}
H、Harder Gcd Problem
比赛的时候就看出来规律了,只是没敢写,从图里面发现每个质数的所有倍数都可以两两组成一对,尽管这个倍数也可能既是2的倍数也可能是5的倍数,那么每个就枚举一个质数,枚举它的倍数 , 两两组成。但是交上去wa掉了,仔细一想,这个做法是贪心的, 那么这个做法到底够不够贪心呢,既然贪了,就要一贪到底。比较两个质数a , b , 如果a < b,那么在n里面肯定是a的倍数比较多,b的倍数比较小,甚至一个没有,既然贪心了,就要把每个数尽量的都要用了,此时对于a来说,它的倍数比较多,也比较好配对,b就相反,所以先配对b,尽量把b的倍数都用了,所以以此类推,枚举质数的时候从大到小枚举
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <map>
#include <list>
#include <queue>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <stack>
#include <set>
#pragma GCC optimize(3 , "Ofast" , "inline")
using namespace std ;
#define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
#define x first
#define y second
typedef long long ll ;
const double esp = 1e-6 , pi = acos(-1) ;
typedef pair<int , int> PII ;
const int N = 2e5 + 10 , INF = 0x3f3f3f3f , mod = 1e9 + 7;
ll in()
{
ll x = 0 , f = 1 ;
char ch = getchar() ;
while(!isdigit(ch)) {if(ch == '-') f = -1 ; ch = getchar() ;}
while(isdigit(ch)) x = x * 10 + ch - 48 , ch = getchar() ;
return x * f ;
}
int prime[N] , vis[N] , tot ;
void get()
{
for(int i = 2; i < N ; i ++) {
if(!vis[i]) prime[++ tot] = i ;
for(int j = 1; j <= tot && i * prime[j] < N ;j ++ ) {
vis[i * prime[j]] = 1;
if(i % prime[j] == 0) break ;
}
}
}
int f[N] ;
void work(){
int n = in() ;
int ans = 0 ;
for(int i = 1; i <= n ;i ++ ) f[i] = 0 ;
int pos = lower_bound(prime + 1, prime + tot + 1 , n) - prime ;
if(prime[pos] > n) pos -- ;
for(int i = pos; i >= 1; i -- ) {
int res = prime[i] ;
for(int j = n / prime[i] * prime[i] ;j > prime[i] ;j -= prime[i]) {
if(f[j]) continue ;
if(!res) res = j ;
else {
ans ++ ;
f[j] = res ;
f[res] = j ;
res = 0 ;
}
}
}
printf("%d
" , ans) ;
for(int i = 0 ;i <= n ;i ++ )
if(f[i] > i)
printf("%d %d
" , i , f[i]) ;
return ;
}
int main()
{
get() ;
int t = in() ;
while(t --) work() ;
return 0 ;
}
/*
*/
待续