题意
给定两个整数 n , k n,k n,k,找到最小的 y y y,使得 gcd ( k , y ) ≤ n \gcd (k,y) \leq n gcd(k,y)≤n,不存在这样的 y y y,则输出 − 1 -1 −1。
分析
由于每次给出的结果是 gcd ( k , y ) \gcd(k,y) gcd(k,y),因此需要枚举小于等于 n n n的素数 x x x,使得 x ∗ k < n x*k<n x∗k<n,故累乘之后的结果即为所求。大数模拟即可。
代码
#include <bits/stdc++.h>
#define fir first
#define sec second
#define pb push_back
#define ll long long
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define pii pair<int,int>
#define debug(x) cerr<<#x<<" =: "<<x<<endl;
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
#define Find find_by_order
#define Order order_of_key
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> indexed_set;
mt19937 mrand(random_device{}());
ll rnd(ll x) { return mrand() % x;}
ll ksm(ll a,ll b,ll mod){ll ans=1;a%=mod;while(b){if(b&1) ans=ans*a%mod;b>>=1;a=a*a%mod;}return ans;}
ll phi(ll n){ll ans=n;for(ll i=2;i*i<=n;i++){if(n%i==0) {while(n%i==0) n/=i;ans=ans*(i-1)/i;}}if(n>1) ans=ans*(n-1)/n;return ans;}
//head
string mul(string a, int b) {
string c;
char s;
int len = a.length();
int ok = 0;
for (int i = len - 1; i >= 0; i--) {
int temp = (a[i] - '0') * b + ok;
ok = temp / 10;
s = temp % 10 + '0';
c = s + c;
}
while (ok) {
s = ok % 10 + '0';
c = s + c;
ok /= 10;
}
return c;
}
bool judge(string a, string b) {
if (a.size() == b.size()) {
int sz = a.size();
for (int i = 0; i < sz; i++) {
if (a[i] == b[i]) ;
else return a[i]<b[i];
}
return 1;
}
return a.size() < b.size();
}
bool isprime(int n){
for(int i=2;i*i<=n;i++) if(n%i==0) return 0;
return 1;
}
int solve(int T) {
int n,k;cin>>n>>k;
string ans=to_string(k);
for(int i=2;i<=n;i++){
if(isprime(i)){
if(judge(mul(to_string(i),k),to_string(n)))ans=mul(ans,i);
}
}
cout<<ans<<endl;
return 0;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
for(int cas=1; cas<=T; cas++) {
solve(T);
}
return 0;
}
题意
给定两个序列
A
,
B
A,B
A,B,长度分别为
n
n
n和
m
m
m,可以构造出一个
n
∗
m
n*m
n∗m的序列
C
C
C,其中
C
i
j
=
A
i
∗
B
j
C_{ij}=A_{i}*B_{j}
Cij=Ai∗Bj。
给出整数
K
K
K,求
C
C
C中第
K
K
K大的值。
分析
显然二分答案
X
X
X,计算
A
[
i
]
∗
B
[
j
]
≤
K
A[i]*B[j] \leq K
A[i]∗B[j]≤K的数量,那么
r
r
r即是答案。
假设当前枚举序列
A
A
A,二分计算存在多少个乘积严格大于
X
X
X。
若
A
[
i
]
<
0
A[i]<0
A[i]<0,需计算
B
[
i
]
≤
X
/
A
[
i
]
B[i] \leq X/A[i]
B[i]≤X/A[i]的数量。
若
A
[
i
]
>
0
A[i]>0
A[i]>0,需计算
B
[
i
]
<
X
/
A
[
i
]
B[i]<X/A[i]
B[i]<X/A[i]的数量,当前计算的乘积是小于
X
X
X的数量,故计入的答案为
m
−
X
m-X
m−X。
若
A
[
i
]
=
=
0
A[i]==0
A[i]==0,乘积必为0,若
X
<
0
X<0
X<0,则长度为
m
m
m的
B
B
B序列都满足。
过程可以手动。
代码
#include <bits/stdc++.h>
#define fir first
#define sec second
#define pb push_back
#define ll long long
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define pii pair<int,int>
#define debug(x) cerr<<#x<<" =: "<<x<<endl;
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
#define Find find_by_order
#define Order order_of_key
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> indexed_set;
mt19937 mrand(random_device{}());
ll rnd(ll x) { return mrand() % x;}
ll ksm(ll a,ll b,ll mod){ll ans=1;a%=mod;while(b){if(b&1) ans=ans*a%mod;b>>=1;a=a*a%mod;}return ans;}
ll phi(ll n){ll ans=n;for(ll i=2;i*i<=n;i++){if(n%i==0) {while(n%i==0) n/=i;ans=ans*(i-1)/i;}}if(n>1) ans=ans*(n-1)/n;return ans;}
//head
const int maxn=1e5+7;
vector<ll>va,vb;
int n,m;ll k;
bool judge(ll x){
ll ret=0;
for(int i=1;i<=n;i++){
if (va[i]==0&&x<0) ret+=m;
else if (va[i]<0) ret+=lower_bound(all(vb),ceil((double)x/va[i]))-(vb.begin()+1);
else if (va[i]>0) ret+=m-((upper_bound(all(vb),floor((double)x/va[i])))-(vb.begin()+1));
}
return ret<=k;
}
// 2
// 2
// 3 4 4 4 5 6 6 6 7
int solve(int T) {
cin>>n>>m>>k;ll x;k--;
for(int i=1;i<=n;i++) cin>>x,va.pb(x);
va.pb(-1e14),va.pb(1e14);vb.pb(-1e14),vb.pb(1e14);
for(int i=1;i<=m;i++) cin>>x,vb.pb(x);
sort(all(va)),sort(all(vb));
ll l=-1e13,r=1e13;
while(r-l>1){
ll mid=(l+r)/2;
if(judge(mid)) r=mid;
else l=mid;
}
cout<<r<<endl;
return 0;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// cin>>T;
int T=1;
for(int cas=1; cas<=T; cas++) {
solve(T);
}
return 0;
}
题意
按照题意进行密码的解密过程
分析
签到题,注意密码的解密是逆向的。
代码
n, m = map(int, input().split())
o = []
s = []
def t1(c):
if c > 'Z':
return int(ord(c) - ord('a'))
else:
return int(ord(c) - ord('A') + 26)
def t2(c):
if c < 26:
return chr(c + ord('a'))
else:
return chr(c + ord('A') - 26)
def tr(s, t):
j = 0
c = ""
for i in range(len(t)):
if j >= len(s):
j = 0
c += (t2((t1(t[i]) - t1(s[j]) + 52) % 52))
j += 1
return c
for i in range(m):
o.append(list(map(int, input().split())))
for i in range(n):
s.append(input())
for i in range(m - 1, -1, -1):
s[o[i][1] - 1] = tr(s[o[i][0] - 1], s[o[i][1] - 1])
for i in range(n):
print(*s[i], sep='', end='\n')
题意
给出一个长度为 n n n的数列 A A A,接下来有 m m m 次操作,操作有两种:
- 1 l r x 1\ l\ r\ x 1 l r x ,表示 i ϵ [ l , r ] i\epsilon [l,r] iϵ[l,r],令 A i = m i n ( A i , x ) A_i=min(A_i,x) Ai=min(Ai,x)
-
2
l
r
k
2\ l\ r\ k
2 l r k ,表示询问区间
[
l
,
r
]
[l,r]
[l,r]中第
k
k
k小的数。
其中: 1 ≤ n , m ≤ 8 ∗ 1 0 4 , 1 ≤ A i ≤ n , 1 ≤ x , k ≤ 1 0 9 1 \leq n,m \leq 8*10^4, 1 \leq A_i \leq n,1 \leq x ,k\leq 10^9 1≤n,m≤8∗104,1≤Ai≤n,1≤x,k≤109
分析
直接分块,维护区间最大的数。
查询第k小,暴力二分即可
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int a[maxn],n,blo,pos[maxn],m;
vector<int>vec[1000];
int Max[maxn];
void reset(int id){
vec[id].clear();
for(int i=(id-1)*blo+1;i<=min(n,id*blo);i++) vec[id].push_back(a[i]);
sort(vec[id].begin(),vec[id].end());
}
void update (int l,int r,int x){
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++) a[i]=min(a[i],x);
reset(pos[l]);
}
else {
for(int i=l;i<=pos[l]*blo;i++) a[i]=min(a[i],x);
reset(pos[l]);
for(int i=pos[l]+1;i<=pos[r]-1;i++) Max[i]=min(Max[i],x);
for(int i=(pos[r]-1)*blo+1;i<=r;i++) a[i]=min(a[i],x);
reset(pos[r]);
}
}
int get(int l,int r,int x){
int ans=0;
if(pos[l]==pos[r]){
for(int i=l;i<=r;i++) ans+=(min(a[i],Max[pos[l]])<=x);
return ans;
}
for(int i=pos[l]+1;i<=pos[r]-1;i++){
if(Max[i]<=x) ans+=blo;
else ans+=upper_bound(vec[i].begin(),vec[i].end(),x)-vec[i].begin();
}
for(int i=l;i<=pos[l]*blo;i++) ans+=(min(a[i],Max[pos[l]])<=x);
for(int i=(pos[r]-1)*blo+1;i<=r;i++) ans+=(min(a[i],Max[pos[r]])<=x);
return ans;
}
int main (){
scanf("%d %d",&n,&m);
blo=sqrt(1.0*n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),pos[i]=(i-1)/blo+1;
for(int i=1;i<=pos[n];i++){
Max[i]=0;
for(int j=(i-1)*blo+1;j<=min(i*blo,n);j++)
vec[i].push_back(a[j]),Max[i]=max(Max[i],a[j]);
sort(vec[i].begin(),vec[i].end());
}
for(int cas=1;cas<=m;cas++){
int op,l,r,k;scanf("%d %d %d %d",&op,&l,&r,&k);
if(op==1) update(l,r,k);
else {
int L=1,R=n,ans;
while(R-L>100){
int mid=(L+R)/2,cnt=get(l,r,mid);
if(cnt>=k) R=mid;
else L=mid;
}
for(int i=L;i<=R;i++){
if(get(l,r,i)>=k) {
printf("%d\n",i);
break;
}
}
// printf("%d\n",L);
}
}
return 0;
}