6232. 最小移动总距离 - 力扣 dp,N - Nunchucks Shop 组合数求不回文的排列,D - Yet Another Problem map记录前缀和的位置

N - Nunchucks Shop 组合数求不回文的排列

可以发现对于每个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<

D - Yet Another Problem map记录前缀和的位置

如果[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) cout<<"2\n";
                else cout<<"-1\n";
            }
        }
    }
    system("pause");
    return 0;
}

6232. 最小移动总距离 - 力扣(LeetCode) dp

按位置对工厂和机器人排序,然后可以发现对于两个机器人一个位于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

1475D - Cleaning the Phone 瞎搞或者二分

用了一种比较勉强但是比较合理的思路乱搞过去了,,,

一开始全用类型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

你可能感兴趣的:(总结,算法,c++,c++,算法,开发语言)