Day1 模拟赛 题解
T1:首先你要发现,对于任意一个奇数i,i xor (i-1)=1;
那么我们可以将答案转化为统计有多少个1相互异或起来;
所以答案就那么几种;
如果你用的数位DP,只能说明你太高估day1T1了;
#include <bits/stdc++.h>
using namespace std;
long long l,r,ans1,ans2;
int main ()
{
int t;
cin>>t;
while(t--){
cin>>l>>r;
if(l>r) swap(l,r);
--l;
ans1=0;
ans2=0;
if(l&1)
{
long long tmp=l/2;
if(tmp&1){
ans1^=0;
}
else{
ans1^=1;
}
}
else{
ans1^=l;
--l;
long long tmp=l/2;
if(tmp&1){
ans1^=0;
}
else{
ans1^=1;
}
}
if(r&1)
{
long long tmp=r/2;
if(tmp&1){
ans2^=0;
}
else{
ans2^=1;
}
}
else{
ans2^=r;
--r;
long long tmp=r/2;
if(tmp&1){
ans2^=0;
}
else{
ans2^=1;
}
}
cout<<(ans1^ans2)<<endl;
}
}
T2:
#include <iostream>
#include <cstdio>
#pragma GCC optimize(2)
using namespace std;
int n,m,p;
struct littlestar{
int to;
int nxt;
int w;
}star[10300000];
int head[10300000],cnt;
void add(int u,int v,int w)
{
star[++cnt].to=v;
star[cnt].w=w;
star[cnt].nxt=head[u];
head[u]=cnt;
}
int floor,tot;
int have[20];
int ans=999999999;
int dis[10300000],vis[10300000],q[10300000];
void spfa()
{
for(register int i=1;i<=tot;i++)
{
dis[i]=999999999;
}
dis[1]=0;
vis[1]=1;
int h=1,t=1;
q[1]=1;
while(h<=t){
int u=q[h];
for(register int j=head[u];j;j=star[j].nxt){
int v=star[j].to;
if(dis[v]>dis[u]+star[j].w){
dis[v]=dis[u]+star[j].w;
if(!vis[v]){
q[++t]=v;
vis[v]=1;
}
}
}
vis[u]=0;
++h;
}
}
int main ()
{
//freopen("library.in","r",stdin);
cin>>n>>m>>p;
floor=1<<p;
tot=n*floor;
for(register int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
for(register int j=0;j<floor;j++){
add(n*j+x,n*j+y,z);
add(n*j+y,n*j+x,z);
}
}
for(register int k=1;k<=p;k++){
int x,u,v,w;
scanf("%d%d%d%d",&x,&u,&v,&w);
for(register int i=0;i<floor;i++){
for(register int j=1;j<=p;j++){
if(i&(1<<(j-1))){
have[j]=1;
}
else have[j]=0;
}
if(have[k]==1){
add(n*i+u,n*i+v,w);
add(n*i+v,n*i+u,w);
}
int tmp=i^(1<<(k-1));
add(n*tmp+x,n*i+x,0);
}
}
spfa();
for(register int i=0;i<floor;i++){
ans=min(ans,dis[i*n+n]);
}
cout<<ans<<endl;
}
T3:
我们首先看到这个题目后,我们可能会想到贪心合并,每次发现不能构成单调不减序列后,我们就一直合并到能构成单调不减序列.这是错误的!因为我们没有保证在相同合并次数下,要尽量使得最后一个数尽量小。所以会想到DP开始思考DP思路设:f[i]表示前i个数合并最小次数g[i]表示前i个数保证在合并f[i]次的情况下,最后一个数的最小值。转移的话,假如我们在处理f[i]那么我们在[1,i]枚举j,假如从j到i这个区间的值的和大于等于g[j](代表一定要合并),那么就可以转移了(合并)那么f[i]=
