C~F Java题解,代码已去除冗余~~~~
构造最小的数字,首先位数一定要最少,那么优先使用数字8,其次在剩下一个圈的时候,需要进坑使得这个首数字尽可能小,因此优先使用4,另外需要特判k为0的时候,时间复杂度O(Tk)
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
for(int i=sc.nextInt();i!=0;i--){
int k=sc.nextInt();
if(k==0){
System.out.println(1);
}
else{
if(k%2==1){
System.out.print(4);
}
for(int j=k/2;j!=0;j--){
System.out.print(8);
}
System.out.println();
}
}
}
}
经观察可知,序列一定是每x-1个偶数后边跟着一个奇数,如此循环的模式,因此只需按规律推导即可,时间复杂度O(T)
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
for(int i=sc.nextInt();i!=0;i--){
int x=sc.nextInt(),p=sc.nextInt();
System.out.println(p%x==0?p/x*2-1:(p-1)/x*(x-1)+(p-1)%x+1<<1);
}
}
}
首先经过观察可知,每个位置的数字一定不小于它的下标,且若进行了修改,一定是对一段前缀进行修改,因此只需要从后往前找到第一个需要修改的位置,并把前缀里面所有出现过的数字的值的出现的最大下标范围内的数字都进行修改即可,注意,根据修改规则和分析,只需修改那些值不等于下标的位置即可,可用set去重,时间复杂度O(Tn)
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
for(int i=sc.nextInt();i!=0;i--){
int n=sc.nextInt(),a[]=new int[n+5],maxIdx=0;
Map<Integer,Integer> map=new HashMap<>();
for(int j=1;j<=n;j++){
a[j]=sc.nextInt();
map.put(a[j],Math.max(j,map.getOrDefault(a[j],0)));
}
a[n+1]=(int)2e9;
for(int j=n;j>0;j--){
if(a[j]>=a[j+1]||a[j]<j){
for(int k=1;k<=j;k++){
if(a[k]!=k){
maxIdx=Math.max(maxIdx,map.get(a[k]));
}
}
break;
}
}
Set<Integer> set=new HashSet<>();
for(int j=1;j<=maxIdx;j++){
if(a[j]!=j){
set.add(a[j]);
}
}
System.out.println(set.size());
}
}
}
位运算,参考资料,时间复杂度O(T*31)
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
for(int i=sc.nextInt();i!=0;i--){
long n=sc.nextInt(),m=sc.nextInt(),ans=0;
for(int j=30;j>=0;j--){
long cur=(1L<<j)*m;
if(n>=cur){
//这一位可以全是1
n-=cur;
ans|=1<<j;
}
else{
cur-=m;
//先测试一下可否后边全为1
if(n>cur){
//说明这一位后边全为1的话,还有剩余,导致后边的数字不应定按位与得到全1,那就想办法使得后边的数字尽可能大
//n-k*(1<<j)<=cost
n-=(1<<j)*((n-cur-1)/(1<<j)+1);
}
}
}
System.out.println(ans);
}
}
}