https://codeforces.com/contest/1088
A
给你数值x,x*x>x , x/x==1<x(x>=2)
ll n,m,t;
cin>>n;
if(n<2)cout<<-1<<endl;
else cout<<n<<" "<<n<<endl;
B
给你长度为n的序列a,要求每次从中间抽出最小的正整数,同时让剩余的数都减这个正整数,输出m个正整数数列。
就是排序,记录减数前缀和,每次用这个前缀和比较原序列,大于0就输出并重新更新前缀和(在这里就是每一次的新的原序列值)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const double eps=1e-9;
const int inf=1e9;
const int maxn=1e5;
bool vis[maxn+5];
ll a[maxn+5];
int main(){
ll n,m,t;
cin>>n>>m;
int sum=0;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
int k=0,temp;
for(int j=0;j<m;j++){
bool f=true;
temp=k;
for(int i=k;i<n;i++){
if(a[i]-sum==0){
temp++;
continue;
}
if(a[i]-sum>0){
cout<<a[i]-sum<<endl;
f=false;
sum=a[i];
break;
}
}
if(f)cout<<0<<endl;
k=temp;
//cout<<sum<<endl;
}
return 0;
}
C
我有长度为n的序列a, 我现在可以操作至多n+1步
OP1:对某前缀序列,所有元素都实现+x
OP2:对某前缀序列,所有元素都实现%x
要求一种方案,使得最后的序列是严格递增的(0,1,2,3,5…)
这题就是直接断定模数为n,因为n+1的操作就是都n个数都OP1,最后OP2得到的解。
每一位的最终态就是位置序。
从最后面开始计算次数和。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const double eps=1e-9;
const int inf=1e9;
const int maxn=1e5;
bool vis[maxn+5];
ll a[maxn+5];
ll b[maxn+5];
int main(){
ll n,m,t;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
a[i]=a[i]%n;
}
int sum=0;
b[n]=0;
if(n-1-a[n-1]>=0){
b[n-1]=n-1-a[n-1];
}
else b[n-1]=(n-1-a[n-1]+n);
a[n-1]=n-1;
sum=b[n-1];
int cnt=b[n-1]>0?1:0;
for(int j=n-2;j>=0;j--){
a[j]=(sum+a[j])%n;
if(j-a[j]>=0)b[j]=j-a[j];
else b[j]=j-a[j]+n;
sum+=b[j];
if(b[j]>0)cnt++;
}
cout<<cnt+1<<endl;
for(int i=0;i<n;i++){
if(b[i]==0)continue;
cout<<"1 "<<i+1<<" "<<b[i]<<endl;
}
cout<<"2 "<<n<<" "<<n<<endl;
return 0;
}
D
交互图,第一次写,懵
机器幕后设定,“a” “b”,你去输入“? c d ” 机器会回复你一些答案;
1 a ^ c > b ^ d
-1.a ^ c < b ^ d
0.a ^ c = b ^ d
要求你给入c d,评测机给你返回结果,你去判断最后的a,b值。
算是找规律吧!
就在逐位判断,tempa=a+1<<i 与b比较大小|||||a与tempb=b+(1<<i)比较大小
两个大小相同,那肯定是这一位的数值不同,所以大的那一位挑1
两个大小不同,且tempa ^ a < b ^ b说明这一位a,b都是1
例如题解中给的例子
Let's simulate for a = 6 and b = 5.
In the first query, we'll send (0, 0) to know that a > b.
In the second query, we'll send (4, 0) (the answer is -1) and (0, 4) (the answer is 1).
Since the answers differ, this bit has the same value for a and b.
Since the answer to the second query is 1, they both have a 1.
Now, curA = curB = 4.
In the third query, we'll send (6, 4) (the answer is -1) and (4, 6) (the answer is -1).
Since the answers are the same, a and b differ in this bit.
Since a is currently the greater, a has a 1 and b has a 0.
Now, the greater is b (the next time 2 bits differ, b will have a 1).
Also, curA = 6 and curB = 4.
In the last query, we'll send (7, 4) (the answer is 0) and (6, 5) (the answer is 0).
Since the answers are the same, a and b differ in this bit.
Since b is currently greater, b has a 1.
Now, curA = 6 and curB = 5 and we're done :D
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const double eps=1e-9;
const int inf=1e9;
const int maxn=1e5;
bool vis[maxn+5];
ll a[maxn+5];
ll b[maxn+5];
int ask(int a,int b){
int res;
printf("? %d %d\n",a,b);
fflush(stdout);
scanf("%d",&res);
return res;
}
int main(){
ll n,m,t;
int jud=0;
ll a=0,b=0,tempa,tempb;
int f=ask(0,0);//判断a,b大小
///为了避免前面的1对后面造成影响,必须连续两位判断
for(ll i=29;i>=0;i--){
tempa=a+(1<<i);//a1000
tempb=b+(1<<i);//b1000
//f是大小结果 temp1是比较(a1000 b0000)的结果 temp2是比较(a0000 b1000)的结果
int temp1=ask(tempa,b);
int temp2=ask(a,tempb);
if(temp1==-1&&temp2==1){///这一位相同且a,b都是1
a=tempa;
b=tempb;
}///若temp1==1&&temp2==-1,那么这一位相同且a,b都是0
else if(temp1==temp2){///这一位不同(1/0)
if(f>0)a=tempa;///a>=b
else b=tempb;
//判断目前a,b大小 不能用ask
f=temp1;//发现temp1就是舍去当前位后,能判断a,b后面数值的大小
}
}
printf("! %lld %lld\n",a,b);
fflush(stdout);
return 0;
}