可以发现对于每个i<=n,j<=n,只要i+j==k我们就可以加上i和j的贡献,所以关键的地方就是算贡献,这其实看起来像组合数,但是如果两个排列或者说方案正着和反着是一样也就是回文的话,那么只保留一种就可以,这个也是有公式的
如果n为偶数,i为奇数,那么就是C(n,i)/2,否则就是(C(n,i)+C(n/2,i/2))/2;
知道这个公式,这个题就结束了
#include
using namespace std;
#define endl '\n'
#define int long long
//const int mod=1e9+7;
const int inf=1e18;
const int N = 1e7+100;
int a[55][55];
int c[55][55];
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
for(int i=0;i<=50;i++)
{
c[i][0]=1;
for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1];
}
for(int i=1;i<=50;i++)
for(int j=0;j<=i;j++)
{
if(i%2==0&&(j&1)) a[i][j]=c[i][j]/2;
else a[i][j]=(c[i][j]+c[i/2][j/2])/2;
}
int ans=0;
int n,k;
cin>>n>>k;
for(int i=0;i<=k&&i<=n;i++)
for(int j=i;j<=k&&j<=n;j++)
{
if(i+j==k)
{
ans+=a[n][i]+a[n][j];
}
}
cout<
如果[L,R]的异或和不为0那么一定是无解的,然后如果[l,r]区间是全0的话就是0步,xr是异或前缀和,pre[i]表示离i最近的j且j=l,那么就可以两步完成,因为[l,r]异或和是0,如果[l,r]中有一段区间[x,r]异或和为0,那么剩下的异或和也一定是0;注意一个特判:如果a[l]=0||a[r]=0,那么只需要一步就够了
#include
using namespace std;
#define endl '\n'
#define int long long
const int mod=1e9+7;
const int inf=1e18;
const int N = 2e5+100;
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int getinv(int a){return qpow(a,mod-2LL);}
int n,q,a[N],nxt[N],xr[N],sum[N],pre[N];
mapmp[2];
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>q;
mp[0][0]=0;sum[0]=xr[0]=0;
for(int i=1;i<=n;i++) pre[i]=0,nxt[i]=n+1;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
xr[i]=xr[i-1]^a[i];
int bit=i&1;
if(mp[!bit].count(xr[i]))
{
int laspos=mp[!bit][xr[i]];
//cout<<"i="<>l>>r;
if((xr[r]^xr[l-1])!=0)
{
cout<<"-1\n";
continue;
}
if(sum[r]-sum[l-1]==0) cout<<"0\n";
else
{
if((r-l+1)&1) cout<<"1\n";
else if(a[l]==0||a[r]==0) cout<<"1\n";
else
{
// cout<=l) cout<<"2\n";
else cout<<"-1\n";
}
}
}
system("pause");
return 0;
}
按位置对工厂和机器人排序,然后可以发现对于两个机器人一个位于x,一个位于y且y>x,那么位于y所选的工厂的位置要大于等于x所选的工厂的位置,这样才是最优的,这样这个题就相对来说简单一点了,先预处理出一个d数组,d[i][j]表示前i个机器人到第j个工厂所用的距离之和,f[i][j]表示前i个机器人到前j个工厂所需要的最小的距离之和,这样转移也是可以想一下的,
f[i][j]=min(f[i][j],f[k][j-1]+d[i][j]-d[k][j])
也就是枚举人数和每个工厂,k是前j-1个工厂所治疗的人数,这样第j个工厂就是进了i-k个人,然后看看第j个工厂进多少人才是最优的,这样是可以把所有情况都枚举到的
动态规划 - 最小移动总距离 - 力扣(LeetCode)
#define ll long long
struct node
{
int pos,lim;
bool operator<(const node &a)const
{
return pos& robot, vector>& factory) {
int ro[205],n=robot.size(),m=factory.size();
sort(robot.begin(),robot.end());
sort(factory.begin(),factory.end());
for(int i=0;i
用了一种比较勉强但是比较合理的思路乱搞过去了,,,
一开始全用类型1,一直加到>=m,如果1全用完 还不行的话就用2再加,用2加到>=m之后就要判断是否可以减去一些1,之后对剩下的2都这样判断,但是其实排完序之后如果当前的这个类型2不行的话以后的就一定不行了,因为是从大到小排序的
#include
using namespace std;
#define endl '\n'
#define int long long
const int mod=998244353;
const int inf=1e18;
const int N = 4e5+100;
const double eps=1e-8;
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int sgn(double x)
{
if(fabs(x)b;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n>>m;
cnt[0]=cnt[1]=0;
priority_queueq;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
cin>>b[i];
f[b[i]&1][++cnt[b[i]&1]]=a[i];
}
sort(f[0]+1,f[0]+cnt[0]+1,cmp);
sort(f[1]+1,f[1]+cnt[1]+1,cmp);
int sum=0,res=0;
for(int i=1;i<=cnt[1];i++)
{
sum+=f[1][i];res++;
//cout<<"sum="<=m) break;
}
int ma=1;
if(sum=m)
{
ma=i+1;
while(!q.empty()&&sum-q.top().val>=m)
{
sum-=q.top().val;res-=q.top().id;q.pop();
}
break;
}
}
}
if(sum=m)
{
sum-=q.top().val;res-=q.top().id;q.pop();
}
}
else
{
break;
}
}
cout<
其实比较正规的解法是二分,对类型1和2从大到小排完序之后枚举使用了多少个1,然后去二分2的使用个数
#include
using namespace std;
#define endl '\n'
#define int long long
const int mod=998244353;
const int inf=1e18;
const int N = 4e5+100;
const double eps=1e-8;
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int sgn(double x)
{
if(fabs(x)b;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n>>m;
cnt[0]=cnt[1]=0;
f[0][0]=f[1][0]=0;
int su=0;
for(int i=1;i<=n;i++) cin>>a[i],su+=a[i];
for(int i=1;i<=n;i++)
{
cin>>b[i];
f[b[i]&1][++cnt[b[i]&1]]=a[i];
}
if(su