题目链接:https://ac.nowcoder.com/acm/contest/5669
B-Basic Gcd Problem
题意:给你一个函数的定义,求解%
输入:
2
3 3
10 5
输出:
3
25
hint:规律
通过举例几个数就可以发现其实他就是在求 ,其中cnt表示n的质因子幂次之和,比如 ,那么cnt=1+2=3,那么。由于输入量有点大,需要提前预处理一下这个cnt,这边采用的是dp处理。还有一点就是需要特判一下n=1的情况cnt=0,所以输出1。
#include<bits/stdc++.h>
#define PB push_back
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define FI first
#define SE second
#define mem(a) memset(a,0,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double pi=acos(-1),eps=1e-8;
const int maxn = 1e6+5;
const int mod = 1e9+7;
LL POW(LL a,LL b,LL p){
LL ans=1;
while(b){
if(b&1)ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
int main(){
vector<int>dp(maxn+1,1);
for(int i=2;i<maxn;i++){
for(int j=2;1LL*i*j<=1e6;j++){
dp[i*j]=max(dp[i*j],dp[i]+dp[j]);
}
}
int t;scanf("%d",&t);
while(t--){
int n,c;scanf("%d%d",&n,&c);
if(n==1)printf("1\n");
else printf("%lld\n",POW(c,dp[n],mod));
}
return 0;
}
F-Finding the Order
题意:给你两条线和线上的四个点ABCD,其中AB在上面一条线 ,CD在下面一条线,给定AC,AD,BC,BD大小,A在B左边,问你四个点的先后顺序。
输入:
2
3 5 5 3
5 3 3 5
输出:
AB//CD
AB//DC
hint:
在CD这条线上找一点设为E,f=AE+BE,过AB做中垂线交CD于F,此时f最小,然后离F点越远,f值越大。
当CD位于F点左侧时,只需要判断和大小即可,前者大的话说明顺序是CD,否则是DC
当CD位于F点右侧时,同理,前者大说明顺序是DC,否则是CD
当CD位于F点两侧时,只需判断AC和BC大小以及AD和BD大小,那D举例子,如果说AD小于BD,那么就说明D在F左边,否则在右边,这就间接得出了CD的左右关系
#include<bits/stdc++.h>
#define PB push_back
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define FI first
#define SE second
#define mem(a) memset(a,0,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double pi=acos(-1),eps=1e-8;
const int maxn = 1e6+5;
const int mod = 1e9+7;
int main(){
int t;scanf("%d",&t);
while(t--){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
int lc,rc,ld,rd;//cd相对f方向
if(a<b)lc=1,rc=0;
else lc=0,rc=1;
if(c<d)ld=1,rd=0;
else ld=0,rd=1;
if(lc&&ld){//都在左侧
if(a+b<c+d)puts("AB//DC");
else puts("AB//CD");
}else if(rc&&rd){//都在右侧
if(a+b<c+d)puts("AB//CD");
else puts("AB//DC");
}else{//在两侧
if(a<b)puts("AB//CD");
else puts("AB//DC");
}
}
return 0;
}
H-Harder Gcd Problem
题意:给你1-n个数,让你取m对互不相同的数,且不放回,使得每对的两个数不互质,求m的最大值,并输出m对。
输入:
2
4
10
输出:
1
2 4
4
3 9
5 10
8 2
4 6
hint:筛法+贪心
贪心策略:倒序查找质数,再以它为基准往上筛,因为大质数能配对的数相对小质数较少,要优先配对大的质数。当筛完的个数是奇数时,可以考虑把其中的一个偶数挑出来,存放在even数组里,最后在even数组中随机配对。
#include<bits/stdc++.h>
#define PB push_back
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define FI first
#define SE second
#define mem(a) memset(a,0,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double pi=acos(-1),eps=1e-8;
const int maxn = 2e5+5;
const int mod = 1e9+7;
bool isprime[maxn],vis[maxn];
int prime[maxn],primesize;
void get_prime(int size){//欧拉筛素数
memset(isprime,true,sizeof(isprime));
isprime[1]=false;
for(int i=2;i<=size;i++){
if(isprime[i])prime[primesize++]=i;
for(int j=0;j<primesize&&i*prime[j]<=size;j++){
isprime[i*prime[j]]=false;
if(i%prime[j]==0)break;
}
}
}
int cnt,n;
pair<int,int>p[maxn];
vector<int>even;
void make(int l,int r){//配对
p[cnt].first=l;
p[cnt++].second=r;
}
void create(vector<int>&v){//数组随机配对
int len=v.size();
for(int i=0;i<len;i+=2){
if(i+1==len)break;
make(v[i],v[i+1]);
}
}
void f(int x){//素数筛取
vector<int>v;
for(int i=x;i<=n;i+=x){
if(!vis[i]){
v.push_back(i);
vis[i]=true;
}
}
int len=v.size();
if(len==1)return;
if(len&1){
for(auto it=v.begin();it!=v.end();it++){
if(*it%2==0){//挑出一个偶数
even.push_back(*it);
v.erase(it);
break;
}
}
}
create(v);
}
void print(){//输出结果
printf("%d\n",cnt);
for(int i=0;i<cnt;i++){
printf("%d %d\n",p[i].first,p[i].second);
}
}
int main(){
get_prime(maxn);
int t;scanf("%d",&t);
while(t--){
memset(vis,false,sizeof(vis));
even.clear();
scanf("%d",&n);cnt=0;
for(int i=n;i>1;i--){
if(isprime[i]){
f(i);
}
}
create(even);
print();
}
return 0;
}