给一个串,由0,1,2组成,2可以用代价a变成0,用代价b变成1,问使其变成由0,1组成的回文串的最小花费
水题。贪心。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define REP(i,st,ed) for(int i=st;i<=ed;++i)
#define IREP(i,st,ed) for(int i=ed;i>=st;--i)
#define TCASE(T) cin>>T;while(T--)
const int MAXN = 100010;
const int MOD = 1e9+7;
const int INF = 1e9+7;
int _;
using namespace std;
int num[205];
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w+",stdout);
FSIO;
int N;
int a, b;
while(cin>>N>>a>>b)
{
for(int i=1;i<=N;++i) cin>>num[i];
int ans = 0;
int flag = 1;
for(int i=1,j=N;iif (num[i]==2&&num[j]==2) ans += 2*min(a,b);
else if(num[i]==2&&num[j]!=2)
{
if(num[j]==0) ans += a;
else ans += b;
}
else if(num[j]==2&&num[i]!=2)
{
if(num[i]==0) ans += a;
else ans += b;
}
else if(num[i]!=2&&num[j]!=2&&num[i]!=num[j])
{
flag = 0;
break;
}
}
if(N%2==1&&num[N/2+1]==2) ans += min(a,b);
if(flag) cout<else cout<<-1<return 0;
}
对一个长为n的串进行反转操作,每次选择p,则反转离p距离小于等于k的所有位置,问使得所有位置都被反转的最小操作次数。
水题。分类讨论,具体见代码。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define REP(i,st,ed) for(int i=st;i<=ed;++i)
#define IREP(i,st,ed) for(int i=ed;i>=st;--i)
#define TCASE(T) cin>>T;while(T--)
const int MAXN = 100010;
const int MOD = 1e9+7;
const int INF = 1e9+7;
int _;
using namespace std;
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w+",stdout);
FSIO;
int N, K;
while(cin>>N>>K)
{
int st = -1;
int ed = -1;
if(N%(2*K+1)==0) st=K+1, ed=N-K;
else if(N%(2*K+1)>K) st=K+1, ed=N-((N%(2*K+1))-K)+1;
else if(N%(2*K+1)<=K) st=1, ed=N-(N%(2*K+1))+1;
int ans = (N+2*K+1-N%(2*K+1))/(2*K+1);
if(N%(2*K+1)==0) ans = (N/(2*K+1));
cout<for (int i=st;i2*K+1))
cout<" ";
cout<return 0;
}
在[1,N]这N个位置上有一个点在运动,每个单位时间移动K步。每个时间你可以给出一个[l,r]询问,如果点在该区间内评测机返回YES,否则是NO。你最多可以询问4500次。
假设在询问某个区间时该点在该区间[l,r]内,那么下一次询问的整个区间范围将会是[l-K,r+K](当然应该是[1,N]的一个子区间。用二分法不断缩小询问区间,直至到一定范围内随机枚举即可,多次试验发现60是最快的(30ms)。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define REP(i,st,ed) for(int i=st;i<=ed;++i)
#define IREP(i,st,ed) for(int i=ed;i>=st;--i)
#define TCASE(T) cin>>T;while(T--)
const int MAXN = 500005;
const ll MOD = 1e9+7;
const int INF = 1e9+7;
int _;
using namespace std;
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w+",stdout);
FSIO;
ll N, K; cin>>N>>K;
string tmp;
srand(time(0));
ll minn = 1, maxn = N;
while (1)
{
if (maxn-minn+1 <= 50)
{
ll attempt = minn + rand()%(maxn-minn+1);
cout << attempt << " " << attempt << endl;
fflush(stdout);
cin >> tmp;
if (tmp[0] == 'N')
{
minn = max(1LL, minn-K);
maxn = min(N, maxn+K);
}
else break;
}
else
{
ll mid = (minn+maxn)>>1;
cout << minn << " " << mid << endl;
fflush(stdout);
cin >> tmp;
if(tmp[0] == 'Y')
{
minn = max(1LL, minn-K);
maxn = min(N, mid+K);
}
else
{
minn = max(1LL, mid-K);
maxn = min(N, maxn+K);
}
}
}
return 0;
}
给一个由N个顶点,M条边组成的有向图,每个点都有权值 ci c i ,给定K, ci c i 属于 [0,2k−1] [ 0 , 2 k − 1 ] 。求这样的对数 (A,x) ( A , x ) ,A是原图的一个可以为空的点集子集,x属于 [0,2k−1] [ 0 , 2 k − 1 ] ,使得A的每个点的权值变为 ci⊕x c i ⊕ x ,且每一条边连接的两个点的权值不同。
根据异或运算的性质: 如果a⊕b=c,那么c⊕b=a 如 果 a ⊕ b = c , 那 么 c ⊕ b = a
所以对每一个相邻的点对 (i,j) ( i , j ) ,当x为 ci⊕cj c i ⊕ c j 时,他们要么被选入A,要么全不被选入A,此时,每个连通分支可以看作一个点。对当前x的选择方案即这样的连通分支的数量(设为t),对答案的贡献为 2t 2 t ,用并查集维护即可。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define REP(i,st,ed) for(int i=st;i<=ed;++i)
#define IREP(i,st,ed) for(int i=ed;i>=st;--i)
#define TCASE(T) cin>>T;while(T--)
const int MAXN = 100010;
const int MOD = 1e9+7;
const int INF = 1e9+7;
int _;
using namespace std;
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w+",stdout);
FSIO;
int N, K;
while(cin>>N>>K)
{
int st = -1;
int ed = -1;
if(N%(2*K+1)==0) st=K+1, ed=N-K;
else if(N%(2*K+1)>K) st=K+1, ed=N-((N%(2*K+1))-K)+1;
else if(N%(2*K+1)<=K) st=1, ed=N-(N%(2*K+1))+1;
int ans = (N+2*K+1-N%(2*K+1))/(2*K+1);
if(N%(2*K+1)==0) ans = (N/(2*K+1));
cout<for (int i=st;i2*K+1))
cout<" ";
cout<return 0;
}#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define REP(i,st,ed) for(int i=st;i<=ed;++i)
#define IREP(i,st,ed) for(int i=ed;i>=st;--i)
#define TCASE(T) cin>>T;while(T--)
const int MAXN = 500005;
const ll MOD = 1e9+7;
const int INF = 1e9+7;
int _;
using namespace std;
int curedgeno;
int tot;
vector<int> rec[MAXN];
mapint > mapp;
struct Edge
{
int u, v;
int next;
Edge(int u=0, int v=0, int next=-1): u(u), v(v), next(next) {}
} edge[MAXN];
void add_edge(int index, int u, int v)
{
++curedgeno;
edge[curedgeno] = Edge(u,v);
rec[index].pb(curedgeno);
}
ll num[MAXN];
ll po2[MAXN];
struct DSU
{
int fa[MAXN], sz;
int n;
void init(int n)
{
this->n = n;
memset(fa,-1,sizeof(fa));
sz = n;
}
int find(int x)
{
return fa[x]==-1 ? x : fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
x=find(x),y=find(y);
if(x>y) swap(x,y);
if(x!=y)
{
fa[x]=y;
sz--;
}
}
int count_p()
{
/*for(int i=1;i<=n;++i) cout<
return sz;
}
} dsu;
int N, M, K;
void init()
{
po2[0] = 1LL;
ll lli = max(N,K);
for(int i=1; i<=lli; ++i)
po2[i]=po2[i-1]*2LL%MOD;
tot=0;
mapp.clear();
for(int i=1; i<=M; ++i) rec[i].clear();
curedgeno = 0;
}
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
for(; !isdigit(ch); ch=getchar())if(ch=='-')f=-1;
for(; isdigit(ch); ch=getchar())x=x*10+ch-'0';
return x*f;
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w+",stdout);
ll u, v;
N =read();
M =read();
K =read();
init();
for(int i=1; i<=N; ++i) num[i]=read();
for(int i=1; i<=M; ++i)
{
u=read();
v=read();
ll tmp = num[u]^num[v];
if(mapp[tmp]) add_edge(mapp[tmp],u,v);
else
{
mapp[tmp] = ++tot;
add_edge(tot,u,v);
}
}
ll ans = (po2[K]-mapp.size()+MOD)*po2[N]%MOD;
dsu.init(N);
for(int tt=1;tt<=tot;++tt)
{
dsu.sz = N;
int sz = rec[tt].size();
for(int i=0; i//DEBUG(dsu.count_p());
ans = (ans+po2[dsu.count_p()])%MOD;
for(int i=0; i1;
dsu.fa[e.u] = -1;
}
}
cout<return 0;
}