niu ke

1

D-小苯的排列构造_牛客小白月赛94 (nowcoder.com)

题目描述
格格有一个长度为 n nn 的排列 p pp,但她不记得 p pp 具体的样子,她只记得数组 a aa。
其中:a i = g c d ( p 1 , p 2 , . . . , p i ) a_i = gcd(p_1, p_2,...,p_i)a 
i

 =gcd(p 
1

 ,p 
2

 ,...,p 
i

 ),也就是说,a i a_ia 
i

  表示排列 p pp 中前 i ii 个数字的最大公约数。

现在,她希望小苯将排列 p pp 复原出来,请你帮帮他吧。

(但有可能无解,这意味着格格给出的 a aa 数组可能是不正确的,此时输出 − 1 -1−1 即可。)

输入描述
输入包含两行。
第一行一个正整数 n   ( 1 ≤ n ≤ 2 × 1 0 5 ) n\ (1 \leq n \leq 2 \times 10^5)n (1≤n≤2×10 
5
 ),表示数组 a aa 的长度。
第二行 n nn 个正整数 a i   ( 1 ≤ a i ≤ n ) a_i\ (1 \leq a_i \leq n)a 
i

  (1≤a 
i

 ≤n),表示数组 a aa 的元素。

输出描述
输出包含一行 n nn 个正整数,表示符合条件的排列 p pp。

如果有多个解,输出任意方案即可。

如果无解,请输出一个数字:− 1 -1−1。

示例
输入

4
4 2 1 1
1
2
输出

4 2 1 3

限制条件

相邻的两个a[]中后一个必须是前一个的因数,必须满足a[i-1] % a[i] = 0,否则无法构造

证明 (ans[i]是最终构造出的数列)

a [ i ] = g c d ( a n s [ 1 ] , . . . a n s [ i ] ) a[i] = gcd(ans[1],...ans[i])a[i]=gcd(ans[1],...ans[i])​
a [ i − 1 ] = g c d ( a n s [ 1 ] , . . . a n s [ i − 1 ] ) a[i-1] = gcd(ans[1],...ans[i-1])a[i−1]=gcd(ans[1],...ans[i−1])​
∴ a [ i ] = g c d ( a [ i − 1 ] , a n s [ i ] ) ∴ a[i] = gcd(a[i-1],ans[i])∴a[i]=gcd(a[i−1],ans[i])​
∴ a [ i − 1 ] ∴ a[i-1]%a[i]=0, ans[i]%a[i]=0∴a[i−1]​

由 a[i-1] % a[i] = 0可知,a是一个非增序列, **a[i - 1]与a[i]**只有两种情况, a[i - 1] == a[i], a[i - 1] > a[i]

当 a[i - 1] > a[i]

由于我们推导出的a[]是递减数列(不一定单调),意味着此时的 a[i] 是第一次出现, 那么数a[i]一定是没使用过的, 该位可以直接填a[i],因为a[i] = gcd(a[i - 1], a[i])是一定成立的,满足我们需要构造的数的条件

当 a[i - 1] == a[i]

那么需要找一个a[i]的未使用倍数

填多少倍:
与1的互换同理, 找一个最小的满足条件的倍数即可

从哪开始找:
不能直接从a[i]开始查找, 会超时
∵ a[i] = gcd(ans[1],…ans[i]) gcd()里的每一个数都是a[i]的倍数
∴ ans[i]是a[i]的倍数, ans[i-1]也是a[i]的倍数, 且 ans[i] > ans[i-1]
所以可以从ans[i-1]+a[i]开始查找

不能从a[i] + a[i] 开始找,如果a[]数组元素全部相同,由于查找上限是n,很容易运行超时

记住每一次取出一个数放入ans[i],就要记录该数为已使用

#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 2e5 + 10;

int n, a[N], ans[N];
bool used[N];

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

int find(int i) 
{
    //查找a[i]的倍数
    // ans[i] > ans[i-1], ans[i-1]也是a[i]的倍数
    for (int f = ans[i - 1] + a[i]; f <= n; f += a[i]) 
    {
        if (!used[f] && gcd(a[i - 1], f) == a[i]) 
        {
            used[f] = true;
            return f;
        }
    }
    return -1;
}

void solve()
{
    cin >> n;
    for (int i = 0; i < n; i ++ ) cin >> a[i];

    for (int i = 1; i < n; i ++)
    {
        if(a[i - 1] % a[i] != 0) //初筛数组 不满足限制条件直接return
        {
            cout << -1 << endl;
            return;
        }
    }
    
    ans[0] = a[0]; //第一个数直接设为a[0]
    used[a[0]] = true ;
    for (int i = 1; i < n; i ++ )
    {
        if (a[i - 1] != a[i])
        {
            ans[i] = a[i];
            used[ans[i]] = true;
        }
        else 
            ans[i] = find(i);
        //cout << ans[i] << endl;
        if (ans[i] == -1) //如果在find()中查找失败 return
        {
            cout << -1 << endl;
            return;
        }
    }
    for (int i = 0; i < n; i ++ ) cout << ans[i] << " ";
    cout << endl;
    return;
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
    solve();

    return 0;
}

2       背包   逻辑运算

E-小苯的01背包(easy)_牛客小白月赛94 (nowcoder.com)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e3 + 9;
int n , k , v[maxn] , w[maxn] , mx;
int main()
{
    cin >> n >> k;
    for(int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];    //体积  价值
    for(int s = 2000; s >= 0; s--)  //枚举答案  答案不会超过最大的wi
    {
        int weight = (1 << 20) - 1; //按位与的初始条件 
        for(int i = 1; i <= n; i++)
        {
            if((s & w[i]) == s)  //可以选的物品
                weight = weight & v[i];  //体积按位与
        }
        if(weight <= k)
        {
            mx = s;
            break;
        }    
    }
    cout << mx;
    return 0;
}

2.5

F-小苯的01背包(hard)_牛客小白月赛94 (nowcoder.com)

上一题, 数据范围2e3, 可以直接从2000开始枚举答案

这一题, 数据范围1e9, 可以从高位开始, 用试填法, 逐位确定

#include<iostream>
#include<climits>
#include<vector>
using namespace std;

int v[200005], w[200005], maxn;
vector<int> memory;

//位运算
int main()
{
	int n, k; cin >> n >> k;
	for (int i = 1; i <= n; i++)
	{
		cin >> v[i] >> w[i];
	}

	for (int s = 30; s >= 0; s--)
	{
		int res = maxn | (1 << s);
		int vol = INT_MAX;
		for (int i = 1; i <= n; i++)
		{
			if ((w[i] & res) == res)
			{
				vol &= v[i];
			}
		}

		if (vol <= k) maxn = res;
	}
	cout << maxn;

	return 0;
}

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
niu-combobox 是基于 jQuery 和 Bootstrap 的下拉框插件,用于方便地创建带搜索框、分页、多选等功能的下拉框。在 JSP 中使用 niu-combobox,需要先引入 jQuery 和 Bootstrap 的相关文件,然后在 JSP 页面中引入 niu-combobox 的 CSS 和 JS 文件,最后在页面中使用相应的 HTML 代码即可。 以下是一个示例: 1. 引入 jQuery 和 Bootstrap 的相关文件 ```html <!-- 引入 jQuery --> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> <!-- 引入 Bootstrap 样式文件 --> <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css"> <!-- 引入 Bootstrap JavaScript 文件 --> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js"></script> ``` 2. 引入 niu-combobox 的 CSS 和 JS 文件 ```html <!-- 引入 niu-combobox 样式文件 --> <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/niuui/1.0.11/niu-combobox.min.css"> <!-- 引入 niu-combobox JavaScript 文件 --> <script src="https://cdn.bootcdn.net/ajax/libs/niuui/1.0.11/niu-combobox.min.js"></script> ``` 3. 在页面中使用 niu-combobox ```html <!-- 创建一个下拉框 --> <select id="mySelect" class="form-control" multiple></select> <!-- 初始化 niu-combobox --> <script> $(function() { $('#mySelect').niucombobox({ url: 'data.json', // 数据源 URL pageSize: 10, // 每页显示的数据条数 searchText: '搜索', // 搜索框提示文字 noDataText: '无数据', // 没有数据时的提示文字 placeholder: '请选择', // 下拉框默认文字 valueField: 'id', // 数据值字段名 textField: 'text', // 数据显示字段名 onSelect: function(selected) { // 选中项发生变化时的回调函数 console.log(selected); } }); }); </script> ``` 其中,data.json 是数据源文件的 URL,需要根据实际情况进行替换。其他配置项的含义可以参考 niu-combobox 的文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值