题意:给定三个数字 x , y , n x,y,n x,y,n。要求去构造一个数组a,满足
a 1 = x , a n = y a_1=x,a_n=y a1=x,an=y
a 1 < a 2 < ⋯ < a n a_1
b i = a i + 1 − a i , b 1 > b 2 > ⋯ > b n b_i=a_{i+1}-a_i,b_1>b_2> \cdots>b_n bi=ai+1−ai,b1>b2>⋯>bn
思路:从后往前去, − 1 , − 2 , − 3 -1,-2,-3 −1,−2,−3,构造即可,最后如果 a 1 < x a_1
//It's better to have sex than to do questions
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define ld long double
using namespace std;
const int N=1005;
const ll md=1e9+7;
const ll inf=1e18;
const double eps=1e-9;
const double E=2.718281828;
//vector>f(n,vector(m,0));
struct graph{
int cnte,hd[N];
struct edge{
int v,nt;
}e[N<<1];
void addedge(int v,int u){
e[++cnte].v=u;
e[cnte].nt=hd[v];
hd[v]=cnte;
}
};
int x,y,n,a[N];
void solve(){
cin>>x>>y>>n;
a[n]=y;
for(int j=1,i=n-1;i>=1;i--,j++){
a[i]=a[i+1]-j;
}
if(a[1]>=x){
a[1]=x;
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
}else{
cout<<-1<<endl;
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--){
solve();
}
}
题意:给定长度为 n n n的字符串s和一个正整数 k k k可以进行以下两个操作任意次
1.交换 s i , s i + 2 s_i,s_{i+2} si,si+2的位置
2.反转长度为 k k k的任意连续子串
求可以达到的字典序最小的字符串
思路:只进行操作一的话,奇数位置上的字母和偶数位置上的是独立的,操作二在 k k k为偶数的情况下可以将奇偶位置联合,奇数则无效果。
如果 k % 2 = 0 k\%2=0 k%2=0则排序输出
反之
奇数位置排序,偶数位置排序,奇偶位置不变输出
//It's better to have sex than to do questions
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define ld long double
using namespace std;
const int N=1005;
const ll md=1e9+7;
const ll inf=1e18;
const double eps=1e-9;
const double E=2.718281828;
//vector>f(n,vector(m,0));
struct graph{
int cnte,hd[N];
struct edge{
int v,nt;
}e[N<<1];
void addedge(int v,int u){
e[++cnte].v=u;
e[cnte].nt=hd[v];
hd[v]=cnte;
}
};
int n,k;
string s;
void solve(){
cin>>n>>k;
cin>>s;
if(k%2==0){
sort(s.begin(),s.end());
cout<<s<<endl;
}else{
vector<char>c[2];
for(int i=0;i<n;i++){
c[i%2].push_back(s[i]);
}
sort(c[0].begin(),c[0].end());
sort(c[1].begin(),c[1].end());
for(int i=0;i<n;i++){
if(i%2==0){
cout<<c[0][i/2];
}else{
cout<<c[1][i/2];
}
}
cout<<endl;
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--){
solve();
}
}
题意:给定一个整数 x x x,通过不大于1000次操作后变成1。
每次可以选择 x x x的一个因素 d d d,将 x : = x − d x:=x-d x:=x−d,相同的 d d d至多选择两次。
(写的很奇怪调了一万年)
思路:考虑每个数字的二进制状态,如果是形如 10000...000 10000...000 10000...000的状态每次减去自身的一半,那么一定等变成1。
如果不是上面的状态那么我们需要变成上面的状态。
考虑减去每个数字的 l o w b i t lowbit lowbit,因为 l o w b i t ( x ) lowbit(x) lowbit(x)一定是 x x x的因数,这样减去第一个1后面的所有的1可以达到2的次幂的状态。
所有的因数被选择不会超过两次,操作的次数不会超过60次
(那如果要求操作次数最小怎么办?)
//It's better to have sex than to do questions
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define ld long double
using namespace std;
const int N=0;
const ll md=1e9+7;
const ll inf=1e18;
const double eps=1e-9;
const double E=2.718281828;
//vector>f(n,vector(m,0));
struct graph{
int cnte,hd[N];
struct edge{
int v,nt;
}e[N<<1];
void addedge(int v,int u){
e[++cnte].v=u;
e[cnte].nt=hd[v];
hd[v]=cnte;
}
};
int lowbit(int x){
return x&(-x);
}
int x;
void solve(){
cin>>x;
vector<int>ans;
ans.push_back(x);
while(x>1){
if(lowbit(x)==x){
x-=x/2;
}else{
x-=lowbit(x);
}
ans.push_back(x);
}
cout<<ans.size()<<endl;
for(int v:ans){
cout<<v<<" ";
}
cout<<endl;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--){
solve();
}
}
题意:给定n*n的01矩阵,可以反转任意的位置(由0变1,由1变0),如果(x,y)被反转,那么所有 x − i ≥ ∣ y − j ∣ x-i\geq|y-j| x−i≥∣y−j∣的位置也被反转。求将所有位置都变成0的最小操作数。
(一眼题,还是调了一万年)
思路:很明显,一个点只会被上面或自身的操作影响,那么操作次数就是一定的了。快速维护每个点当前的01状态即可。
每个点的01状态由自身的初始值和其被操作的次数的奇偶确定。
考虑维护两个斜线的前缀和,形如:
5 4 3 2 1
6 5 4 3 2
7 6 5 4 3
8 7 6 5 4
9 8 7 6 5
和
9 8 7 6 5
8 7 6 5 4
7 6 5 4 3
6 5 4 3 2
5 4 3 2 1
设上区域内被操作的次数的和为A
设下区域内被操作的次数的和为B
那么当前这个点被操作的次数为A-B
树状数组维护单点修改,和单点查询即可。
复杂度为 O ( n 2 l o g ( n ) ) O(n^2log(n)) O(n2log(n))
//It's better to have sex than to do questions
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define ld long double
using namespace std;
const int N=3005;
const ll md=1e9+7;
const ll inf=1e18;
const double eps=1e-9;
const double E=2.718281828;
//vector>f(n,vector(m,0));
struct graph{
int cnte,hd[N];
struct edge{
int v,nt;
}e[N<<1];
void addedge(int v,int u){
e[++cnte].v=u;
e[cnte].nt=hd[v];
hd[v]=cnte;
}
};
struct bit{
int n;
vector<int>num;
bit(int n):n(n),num(n+1,0){}//初始化
int lowbit(int x){
return x&(-x);
}
void add(int i,int v){ //在i位置加上k
while(i <= n){
num[i] += v;
i += lowbit(i);
}
}
int sum(int i){//求A[1 - i]的和
int res = 0;
while(i > 0){
res += num[i];
i -= lowbit(i);
}
return res;
}
};
int n,op[N][N],opp[N];
string s[N];
int getida(int x,int y){
return abs(x-1)+abs(n-y)+1;
}
int getidb(int x,int y){
return abs(n-x)+abs(n-y)+1;
}
void solve(){
cin>>n;
for(int i=0;i<n;i++){
cin>>s[i];
}
bit A(n*2),B(n*2);
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int ida=getida(i,j);
int idb=getidb(i,j);
int op=A.sum(ida)-B.sum(idb-1);
// cout<
if((op%2+(s[i-1][j-1]-'0'))%2){
ans++;
A.add(ida,1);
B.add(idb,1);
}
}
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--){
solve();
}
}
题意:给定一个长度为n的数组S,每次随机选两个数a和b,分别告诉Alice和Bob,再告诉他们这两个数子按位或的值,他们只能说“我不知道”或者“我知道”,直到确切的猜出 a < b , a > b , o r a = b ab , or \quad a=b a<b,a>b,ora=b,求轮流次数的期望值。
(C,D花太多时间,还想得很奇怪遂寄)
一眼想到小时候看的一个国产动漫叫《端脑》,不同的是告诉俩人的是a*b,然后猜准确的值。但赛时没有AC。
思路:看到 0 ≤ s i < 2 30 0\leq s_i <2^{30} 0≤si<230,和按位或应该就可以想到按位去判断。
(但是赛时没有)
考虑从高位向低位判断,考虑当前位置
如果是(0,0)
那么不需要询问,直接看下一位置。
如果是(0,1)
经过一轮判断出大小
如果是(1,0)
经过两轮判断出大小
如果是(1,1)
经过一轮可以判断出当前位相等,然后看下一位。
如果都相等,也就是所有位置都判断完成,则需要额外一次判断两者相等。
把所有数字插入字典树,然后挨个去询问即可
最后将得出的总数除以方案总数即使答案。
//It's better to have sex than to do questions
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define ld long double
using namespace std;
const int N=2e5+5;
const ll md=998244353;
const ll inf=1e18;
const double eps=1e-9;
const double E=2.718281828;
//vector>f(n,vector(m,0));
struct graph{
int cnte,hd[N];
struct edge{
int v,nt;
}e[N<<1];
void addedge(int v,int u){
e[++cnte].v=u;
e[cnte].nt=hd[v];
hd[v]=cnte;
}
};
int trie[N<<5][2],cnt=0;
ll val[N<<5];
ll n,s[N];
ll ksm(ll a,ll b){
ll res=1;
while(b){
if(b&1)res=res*a%md;
a=a*a%md;
b>>=1;
}
return res;
}
ll getinv(ll a,ll b){
return ksm(a,b-2);
}
void insert(int x){
int now=0;
for(int i=29;i>=0;i--){
int wd=x>>i&1;
if(!trie[now][wd]){
trie[now][wd]=++cnt;
}
now=trie[now][wd];
val[now]++;
}
}
ll res=0;
void dfs(int x,int pos,int now){
// cout<
if(pos<1){
// cout<<"pos<1 "<
res+=val[x];
res%=md;
return ;
}
int wd=now>>(pos-1)&1;
if(wd){//1
res=((res+2ll*val[trie[x][0]]%md)%md+1ll*val[trie[x][1]]%md)%md;
}else{//0
res=(res+1ll*val[trie[x][1]]%md)%md;
}
// cout<<"res up"<
if(trie[x][1]&&wd){
dfs(trie[x][1],pos-1,now);
}
if(trie[x][0]&&!wd){
dfs(trie[x][0],pos-1,now);
}
}
void solve(){
cin>>n;
for(int i=0;i<=n<<5;i++){
trie[i][0]=trie[i][1]=0;
val[i]=0;
}
res=0;
for(int i=1;i<=n;i++){
cin>>s[i];
insert(s[i]);
}
for(int i=1;i<=n;i++){
dfs(0,30,s[i]);
}
// cout<
ll ans=res*getinv(n*n%md,md)%md;
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--){
solve();
}
}
(持续补题。。。。)