HBU Medium problem set

可能没很多人看,后面没写思路,有问题单独问我吧

目录

7-1 区间翻转

7-2 次大值的和

7-3 买东西

7-4 双重子串

7-5 对决

7-6 最大公约数

7-7 填数字

7-8 放小球

7-9 给树染色

7-10 摆放小球

7-11 区间的个数

7-12 选零食

7-13 小球之间的距离

7-14 1还是2

7-15 青春猪头之我没学过C语言

7-16 打怪兽

7-17 背上书包去旅行

7-18 向前走

7-19 热水器

7-20 走方格

7-21 朋友圈

7-22 走方格

7-23 和与积

7-24 增加硬币

7-25 日落大道

7-26 ICPC保定站

7-27 简单的异或

7-28 选我啊!

7-29 豪华酒店

7-30 摆放小球

7-31 最大公约数的和

7-32 一道简单题

7-33 一个无限大的集合


7-1 区间翻转

思路:

贪心,我们每次操作,除最后是这种“RRRRRL” 或 “LRRRR” 操作后只能使满意度+1的特殊情况外,总能使满意度+2.

代码:

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 200010, M = N * 2;
int n, m, r1, r2;
string s;
int main() {
    cin >> n >> m;
    getchar();
    cin >> s;
    int res = 0;
    for (int i = 0; i < n - 1; i++) {
        if (s[i] == s[i + 1])res++;
    }
    res = min(res + m * 2, n - 1);
    cout << res;
    return 0;

}

7-2 次大值的和

思路:

计算每一个值的对结果的贡献。即它作为次大值出现是什么情况。

即左边出现一个比他大的值&&右边没有比他大的值,或者对称情况

这里要用单调栈来算每个数左边距离其最近的比它大的数,右边同理,最后将这些情况的结果计算出来,详见代码。

代码:

#include 
using namespace std;
const int N = 1000010;
int n;
int a[N],b[N];
int l_low[N], l_up[N], r_low[N], r_up[N];
long long res;
int stk1[N], stk2[N], tt;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        b[a[i]] = i;
    }
    for (int i = 1; i <= n; i++) {
        while (tt && a[stk1[tt]] < a[i])tt--;
        if (!tt) {
            l_low[i] = 1;
            l_up[i] = -1;
        }
        else {
            l_low[i] = stk1[tt] + 1;
            l_up[i] = stk1[tt];
        }
        stk1[++tt] = i;
    }
    tt = 0;
    for (int i = n; i >= 1; i--) {
        
        while (tt && a[stk2[tt]] < a[i])tt--;
        //cout << tt << " " << stk2[tt] << endl;
        if (!tt) {
            r_low[i] = n;
            r_up[i] = -1;
        }
        else {
            r_low[i] = stk2[tt] - 1;
            r_up[i] = stk2[tt];
        }
        stk2[++tt] = i;
    }
    for (int i = 1; i <= n; i++) {
        int llow = i - l_low[i];
        int rlow = r_low[i] - i;
        int lup, rup;
        if (l_up[i] == -1) {
            lup = 0;
        }
        else {
            lup = 1;
            while (--l_up[i] && a[i] > a[l_up[i]])lup++;
        }
        if (r_up[i] == -1) {
            rup = 0;
        }
        else {
            rup = 1;
            while (++r_up[i] != n + 1 && a[i] > a[r_up[i]])rup++;
        }
        //cout << llow << " " << lup << " " << rlow << " " << rup << endl;
        res += ((long long)(llow + 1) * rup + (long long)(rlow + 1)  * lup) * a[i];

    }
    cout << res;
    return 0;
}

7-3 买东西

思路:

贪心:每次用一张券使得最贵的物品价格除以2

代码:

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 100010, M = N * 2, mod = 1e9 + 7;
int n, m;
priority_queue q;

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        q.push(x);
    }
    while (m--) {
        int x = q.top();
        if (x == 0)break;
        q.pop();
        q.push(x / 2);
    }
    LL sum = 0;
    while (!q.empty()) {
        sum += q.top();
        q.pop();
    }
    cout << sum;
}

7-4 双重子串

simple 里有

7-5 对决

思路:

将某两个人的比赛看成一个节点,因为每个人都要按已有的顺序比赛,所以给每个人先比的比赛到后比的比赛建一条边,然后做一遍关键路径 ,即完成所有任务所需要的最长时间。

代码:

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 1e6+10, M = 1e6+10, mod = 1e9 + 7;
int n, m, x;
map mp;
int h[N], e[M], ne[M], idx;
int d[M],f[M];
int cnt;
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int get(int a, int b) {
    if (a > b)swap(a, b);
    if (mp.count(make_pair(a,b)) == 0)mp[make_pair(a, b)] = ++cnt;
    return mp[{a, b}];
}

int main()
{
    cin >> n;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i++) {
        cin >> x;
        int lst = get(i, x);
        for (int j = 1; j <= n - 2; j++) {
            cin >> x;
            x = get(i, x);
            add(lst, x);
            d[x]++;
            lst = x;
        }
    }
    queue q;
    for (int i = 1; i <= n * (n - 1) / 2; i++)if (!d[i])q.push(i),f[i] = 1;
    int res = 0;
    while (q.size()) {
        int t = q.front();
        q.pop();
        res++;
        for (int i = h[t]; ~i; i = ne[i]) {
            int j = e[i];
            if (--d[j] == 0)q.push(j);
            f[j] = max(f[j], f[t] + 1);
        }
    }
    if (res != (n - 1) * n / 2)puts("-1");
    else {
        int num = 0;
        for (int i = 1; i <= (n - 1) * n / 2; i++)num = max(num, f[i]);
        cout << num;
    }
    return 0;
}

7-6 最大公约数

思路:

这题有个结论:最大公约数一定是数组求和的一个约数

做法:

数组求和sum,计算每个约数能不能满足要求(看看能不能在m次操作内把这个数组变为全0)

代码:

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 200010, M = N * 2, mod = 1e9 + 7;
int n, m;
int a[N],b[N];
int sum;

bool check(int x) {
    int s = 0,t = 0;
    for (int i = 0; i < n; i++) {
        b[i] = a[i] % x;
        s += b[i];
    }
    if (s % x != 0)return false;
    t = s / x;
    sort(b, b + n);
    for (int i = n - 1; t ; i--,t--) {
        s -= b[i];
    }
    if (s <= m)return true;
    else return false;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        sum += a[i];
    }
    int res = 0;
    for (int i = 1; i <= sum / i; i++) {
        if (sum % i == 0) {
            if (check(i))res = max(res, i);
            if (check(sum / i))res = max(res, sum / i);
        }
    }
    cout << res;
}

7-7 填数字

思路:

DP f[i][j] 表示前i位数,对13取模余j的方案数

初始化第一位,如果是问号,初始化0~9,否则是几就初始化几

转移方程: f[i][(j * 10 + s[i] - '0') % 13] +=  f[i - 1][j] ;

思考一个点:19对13取余得6 , 192对13取余 等价于19对13取余的结果6 乘10 再加 2 再对13取余

代码:

#include 
#include 
#include 
using namespace std;
const int N = 1e5+10,mod = 1e9 + 7;
int n;
int f[N][13];
int main()
{
    string s;
    cin>>s;
    s = " " + s;
    if(s[1] == '?'){
        for(int i=0;i<10;i++)f[1][i] = 1;
    }else f[1][s[1] - '0'] = 1;

    for(int i = 2;i < s.size();i++){
        bool fg = (s[i] == '?');
        for(int j = 0;j < 13;j++){
            if(f[i - 1][j]){
                if(fg){
                    for(int k = 0;k < 10;k ++){
                        f[i][(j*10 + k) % 13] = (f[i][(j*10 + k) % 13] + f[i - 1][j]) % mod;
                    }
                }else f[i][(j * 10 + s[i] - '0') % 13] = (f[i][(j * 10 + s[i] - '0') % 13] + f[i - 1][j]) %mod;
            }
        }
    }
    cout<

7-8 放小球

这道题,我们一定能通过一种方式将最终解构造出来

从后往前遍历

如果当前箱子的倍数箱子放小球数对2取余不满足这个属性,那就在这个箱子放,否则不放

代码:

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 200010, M = N * 2, mod = 1e9 + 7;
int n, m;
int a[N],b[N];
vector res;
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = n; i >= 1; i--) {
        int sum = 0;
        for (int k = 2; i * k <= n; k++)sum += b[i * k];
        if (sum % 2 == 0) {
            if (a[i]) {
                res.push_back(i);
                b[i] = 1;
            }
        }
        else {
            if(!a[i]) {
                res.push_back(i);
                b[i] = 1;
            }
        }
    }
    cout << res.size() << endl;
    for (int i = 0; i < res.size(); i++) {
        cout << res[i] << " ";
    }
}

7-9 给树染色

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 100010, M = N * 2, mod = 1e9 + 7;
int n, m;
int tol[N];
int h[N], e[M], ne[M], idx;
LL sum = 1;
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs1(int cur, int fa) {
    int x;
    if (cur == 1)x = m - 1;
    else x = m - 2;
    for (int i = h[cur]; i != -1; i = ne[i]) {
        int j = e[i];
        if (j == fa)continue;
        tol[j] = x--;
        dfs1(j, cur);
    }
}
void dfs2(int u, int fa) {
    sum = (sum * tol[u]) % mod;
    for (int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
        if (j == fa)continue;
        dfs2(j, u);
    }
}


int main() {
    cin >> n >> m;
    memset(h, -1, sizeof h);
    for (int i = 1; i < n; i++) {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
    }
    tol[1] = m;

    dfs1(1, 0);
    dfs2(1, 0);
    cout << sum;

}

7-10 摆放小球

#include 
using namespace std;
typedef long long LL;
const int N = 2010, mod = 1e9 + 7;
int n, a, b, x;
int fact[N], infact[N];
int qmi(int a, int k, int p) {
    int res = 1;
    while (k) {
        if (k & 1)res = (LL)res * a % p;
        k >>= 1;
        a = (LL)a * a % p;
    }
    return res;
}
int C(int a, int b) {
    return (LL)fact[a] * infact[b] % mod * infact[a - b] % mod;
}

int main() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i < N; i++) {
        fact[i] = (LL)fact[i - 1] * i % mod;
        infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }

    scanf("%d%d", &n, &x);
    for (int i = 1; i <= x; i++) {
        if (i > n - x + 1)cout << 0 << endl;
        else cout << (LL)C(n - x + 1, i) * C(x - 1,i - 1) % mod <

7-11 区间的个数

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 1e5+10, M = 1e6+10, mod = 1e9 + 7;
int n;
LL m;
LL a[N];
int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i++)cin >> a[i];
    int l = 0, r = 0;
    LL res = 0;
    LL sum = 0;
    while (r < n) {
        while(sum < m && r < n) {
            sum += a[r];
            r++;
        }
        if (sum >= m)res += n - r + 1;
        sum -= a[l++];
        while (sum >= m) {
            sum -= a[l++];
            res += n - r + 1;
        }
    }
    cout << res;
    return 0;
}

7-12 选零食

#include 
using namespace std;
typedef long long LL;
typedef pair PII;
const int N = 55;

int n, m;
int a[N];
int res;
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	int buy = min(n, m);
	for (int i = 1; i <= buy; i++) {
		int put = m - i;
		for (int jl = 0; jl <= i; jl++) {
			int sum = 0;
			priority_queue, greater> q;
			int jr = n - i + jl + 1;
			for (int j = 1; j <= jl; j++) {
				q.push(a[j]);
				sum += a[j];
			}
			for (int j = jr; j <= n; j++) {
				q.push(a[j]);
				sum += a[j];
			}
			int x = put;
			while (!q.empty() && q.top() < 0 && x > 0) {
				sum -= q.top();
				q.pop();
				x--;
			}
			res = max(res, sum);
		}
	}
	cout << res;
	return 0;
}

7-13 小球之间的距离

#include 
using namespace std;
typedef long long LL;
const int N = 2e5 + 10, mod = 1e9 + 7;
int n, m, k;

int qmi(int a, int k, int p)
{
    int res = 1;
    while (k)
    {
        if (k & 1) res = (LL)res * a % p;
        a = (LL)a * a % p;
        k >>= 1;
    }
    return res;
}


int C(int a, int b, int p)
{
    if (b > a) return 0;

    int res = 1;
    for (int i = 1, j = a; i <= b; i++, j--)
    {
        res = (LL)res * j % p;
        res = (LL)res * qmi(i, p - 2, p) % p;
    }
    return res;
}


int main() {
    cin >> n >> m >> k;
    int tmp = (LL)m * m % mod;
    LL sum = 0,sum2 = 0;
    for (int i = 1; i < n; i++) {
        sum = (sum + (LL)i * (n - i) % mod) % mod;
    }
    sum = sum * tmp % mod;
    tmp = (LL)n * n % mod;
    for (int i = 1; i < m; i++) {
        sum2 = (sum2 + (LL)i * (m - i) % mod) % mod;
    }
    sum2 = sum2 * tmp % mod;

    sum = ((sum + sum2) % mod * C(n * m - 2, k - 2, mod)) % mod;
    cout << sum;
    return 0;
}

7-14 1还是2

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 1e5+10, M = 1e6+10, mod = 1e9 + 7;
int n, m;
int p[N];

int find(int x) {
    if (x != p[x])p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)p[i] = i;
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        a = find(a), b = find(b);
        if (a != b)p[a] = b;
    }
    set st;
    for (int i = 1; i <= n; i++) {
        p[i] = find(p[i]);
        st.insert(p[i]);
    }
    cout << st.size();
    return 0;
}

7-15 青春猪头之我没学过C语言

#include 
using namespace std;
typedef pair PII;
typedef long long LL;
const int N = 1e5+10, M = 1e6+10, mod = 1e9 + 7;
int n;
LL x, y;
LL fun(LL x) {
    if (x % 4 == 1)return 1;
    else if (x % 4 == 2)return x + 1;
    else if (x % 4 == 3)return 0;
    else return x;
}
int main()
{
    cin >> x >> y;
    LL res = fun(max((LL)0,x - 1)) ^ fun(y);
    cout << res;
    
    return 0;
}

7-16 打怪兽

#include
#include
#include
#include
#include
#include
using namespace std;
#define clr(a,b) memset(a,b,sizeof(a))
const int maxn=700+2;
const int inf=0x3f3f3f3f;
typedef long long ll;
struct Node
{
    int maxw,cnt;
    Node(){}
    Node(int maxw,int cnt):maxw(maxw),cnt(cnt){}
    bool operator > (Node t)
    {
        return maxw>t.maxw;
    }
}tree[maxn<<2][maxn<<2];
int m,n,q,r,mat[maxn][maxn];
Node ans;
void push_upy(int deep,int k)
{
    tree[deep][k].maxw=max(tree[deep][k<<1].maxw,tree[deep][k<<1|1].maxw);
    if(tree[deep][k].maxw==tree[deep][k<<1].maxw)
    tree[deep][k].cnt+=tree[deep][k<<1].cnt;
    if(tree[deep][k].maxw==tree[deep][k<<1|1].maxw)
    tree[deep][k].cnt+=tree[deep][k<<1|1].cnt;
    return ;
}
void push_upx(int deep,int k)
{
    tree[deep][k].maxw=max(tree[deep<<1][k].maxw,tree[deep<<1|1][k].maxw);
    if(tree[deep][k].maxw==tree[deep<<1][k].maxw)
    tree[deep][k].cnt+=tree[deep<<1][k].cnt;
    if(tree[deep][k].maxw==tree[deep<<1|1][k].maxw)
    tree[deep][k].cnt+=tree[deep<<1|1][k].cnt;
    return ;
}
void bulid_y(int ly,int ry,int deep,int k,int flag)
{
    tree[deep][k].maxw=-inf;
    if(ly==ry)
    {
        if(flag)
        {
        scanf("%d",&tree[deep][k].maxw);
        mat[r][ly]=tree[deep][k].maxw;
        tree[deep][k].cnt=1;
        }
        else {push_upx(deep,k);}//更新x方向
        return ;
    }
    int mind=(ly+ry)>>1;
    //bulid_y(ly,mind,deep,k<<1,flag);
    bulid_y(ly,mind,deep,k<<1,flag);
    bulid_y(mind+1,ry,deep,k<<1|1,flag);
    push_upy(deep,k);
    return ;
}
void bulid_x(int lx,int rx,int deep)
{
    if(lx==rx)
    {
        r=lx;
        bulid_y(1,n,deep,1,1);
        return ;
    }
    int mind=(lx+rx)>>1;
    bulid_x(lx,mind,deep<<1);
    bulid_x(mind+1,rx,deep<<1|1);
    bulid_y(1,n,deep,1,0);//同区域y轴方向
    return ;
}
void query_y(int ly,int ry,int Ly,int Ry,int deep,int k)
{
    if(Ly<=ly&&ry<=Ry)
    {
        if(ans.maxw==tree[deep][k].maxw)
        {
            ans.cnt+=tree[deep][k].cnt;
        }
        else if(tree[deep][k]>ans)
        {
            ans=tree[deep][k];
        }
        return;
    }
    int mind=(ly+ry)>>1;
    if(Ly<=mind)
    query_y(ly,mind,Ly,Ry,deep,k<<1);
    if(Ry>mind)
    query_y(mind+1,ry,Ly,Ry,deep,k<<1|1);
    return ;
}
void query_x(int lx,int rx,int Lx,int Rx,int Ly,int Ry,int deep)
{
    if(Lx<=lx&&rx<=Rx)
    {
        query_y(1,n,Ly,Ry,deep,1);
        return;
    }
    int mind=(lx+rx)>>1;
    if(Lx<=mind)
    query_x(lx,mind,Lx,Rx,Ly,Ry,deep<<1);
    if(Rx>mind)
    query_x(mind+1,rx,Lx,Rx,Ly,Ry,deep<<1|1);
    return ;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        scanf("%d%d",&m,&n);
        clr(tree,0);
        clr(mat,0);
        bulid_x(1,m,1);
        scanf("%d",&q);
        int x1,y1,x2,y2;
        while(q--)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            ans.maxw=0;
            ans.cnt=0;
            query_x(1,m,x1,x2,y1,y2,1);
            
            printf("%d\n",ans.maxw);
      
        }
    }
   return 0;
}

7-17 背上书包去旅行

#include 
using namespace std;
typedef long long LL;
const int N = 20,M = 1 << N, mod = 1e9 + 7;
int n, m;
int w[N][N];
int f[M][N];
struct NODE {
    int a, b, c;
}node[N];
 
int main()
{
    cin >> n;
    int i = 0;
    for (; i < n; i++)
        cin >> node[i].a >> node[i].b >> node[i].c;
    node[i].a = node[0].a, node[i].b = node[0].b, node[i].c = node[0].c;
    n++;
    for (i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            w[i][j] = abs(node[j].a - node[i].a) + abs(node[j].b - node[i].b) + max(0, node[j].c - node[i].c);
        }
    }
    memset(f, 0x3f, sizeof(f));
    f[1][0] = 0;
    for (i = 1; i < (1 << n); i++) {
        for (int j = 0; j < n; j++) {
            if (i >> j & 1) {
                for (int k = 0; k < n; k++) {
                    if (i >> k & 1) {
                        f[i][j] = min(f[i][j], f[i - (1 << j)][k] + w[k][j]);
                    }
                }
            }
        }
    }
    cout << f[(1 << n) - 1][n - 1];
    return 0;
}

7-18 向前走

#include 
using namespace std;
typedef long long LL;
const int N = 200010;
int n,w;
LL s[N],t[N];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&s[i]);
        s[i]+=s[i-1];
        t[i] = max(s[i],t[i-1]);
        //cout<

7-19 热水器

#include 
using namespace std;
typedef long long LL;
const int N = 200010;
LL n,w;
LL s[N];

int main()
{
    scanf("%lld%lld",&n,&w);
    int l,r,c,maxn=0;
    for(int i=0;iw){
            fg=false;
            break;
        }
    }
    if(fg)printf("Yes");
    else printf("No");
    return 0;
}

7-20 走方格

#include 
using namespace std;
typedef long long LL;
const int N = 2010, mod = 1e9 + 7;
int n, m;
char ch[N][N];
LL f[N][N];
LL s1[N][N],s2[N][N],s3[N][N];

int main()
{
    scanf("%d%d", &n, &m);
    getchar();
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++)scanf("%c", &ch[i][j]);
        getchar();
    }
    f[1][1] = 1,s1[1][1]= s2[1][1] = s3[1][1] =1;
    for(int i=1;i<=n;i++)
        for (int j = 1; j <= m; j++) {
            if (ch[i][j] == '#') { continue; }
            f[i][j] += ((s1[i - 1][j] + s2[i][j - 1])%mod + s3[i - 1][j - 1])%mod;
            s1[i][j] = (f[i][j] + s1[i - 1][j])%mod;
            s2[i][j] = (f[i][j] + s2[i][j - 1]) % mod;
            s3[i][j] = (f[i][j] + s3[i - 1][j - 1]) % mod;
        }
    /*for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cout << f[i][j]<<" ";
        }
        cout << endl;
    }*/
        
    cout << f[n][m];
    return 0;
}


7-21 朋友圈

#include 
using namespace std;
typedef long long LL;
const int N = 200010, mod = 1e9 + 7;
int n, q, x;
int a, b, c;
int p[N];
map res[N];
int siz[N];
int find(int x) {
    if (x != p[x])p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++) {
        siz[i] = 1;
        scanf("%d", &x);
        res[i][x]++;
        p[i] = i;
    }
    while (q--) {
        scanf("%d%d%d" ,&c, &a, &b);
        if (c == 1) {
            a = find(a), b = find(b);
            if (a != b) {
                if (siz[a] > siz[b]) {
                    p[b] = a;
                    siz[a] += siz[b];
                    for (auto it : res[b]) {
                        res[a][it.first] += it.second;
                    }
                }
                else {
                    p[a] = b;
                    siz[b] += siz[a];
                    for (auto it : res[a]) {
                        res[b][it.first] += it.second;
                    }
                }
            }
        }
        else {
            a = find(a);
            printf("%d\n", res[a][b]);
        }
    }
    return 0;
}


7-22 走方格

#include 
using namespace std;
typedef long long LL;
const int N = 200010, mod = 1e9 + 7;
int n, m, a, b;

int fact[N], infact[N];
int qmi(int a, int k, int p)
{
    int res = 1;
    while (k)
    {
        if (k & 1) res = (LL)res * a % p;
        a = (LL)a * a % p;
        k >>= 1;
    }
    return res;
}


LL com(int n, int m) {
    return ((LL)fact[n] * infact[m] % mod * infact[n - m]) % mod;
}


int main()
{
    scanf("%d%d%d%d", &n, &m, &a, &b);
    fact[0] = infact[0] = 1;
    for (int i = 1; i < N; i++)
    {
        fact[i] = (LL)fact[i - 1] * i % mod;
        infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }
    LL res = 0;
    for (int i = 0; i < n - a; i++) {
        LL t = ((LL)com(b + i - 1, b - 1) * com(n + m - b - i - 2, n - i - 1))%mod;
        res = (res + t)%mod;
    }
    cout << res;
    return 0;
}


7-23 和与积

#include 
using namespace std;
typedef long long LL;
LL S, P;
int main()
{
    cin >> S >> P;
    LL j = 0;
    for (LL i = 1; i <= P/i; i++) {
        j = S - i;
        if ((LL)i * j == P) {
            cout << "Yes";
            return 0;
        }
    }
    cout << "No";
    return 0;
}


7-24 增加硬币

#include 
using namespace std;
typedef long long LL;
const int N = 110;
double f[N][N][N];
int d = 0;

double dp(int a, int b, int c) {
    if (f[a][b][c] >= 0)return f[a][b][c];
    f[a][b][c] = 0;
    if (a >= 100 || b >= 100 || c >= 100)return f[a][b][c];
    int sum = a + b + c;
    f[a][b][c] += (dp(a + 1, b, c) + 1) * (1.0 * a) / sum;
    f[a][b][c] += (dp(a, b + 1, c) + 1) * (1.0 * b) / sum;
    f[a][b][c] += (dp(a, b, c + 1) + 1) * (1.0 * c) / sum;
    return f[a][b][c];
}
int main()
{
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    memset(f, -1, sizeof f);
    printf("%.9lf", dp(a, b, c));

    return 0;
}

7-25 日落大道

#include 
using namespace std;
typedef long long LL;
typedef pair PII;
const int N = 2010;
int n, m;
char ch;
char s[N][N];
int d[N][N];

vector mp[30];
int dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };

int main()
{
    scanf("%d%d", &n, &m);
    getchar();
    int x, y, resx, resy;
    memset(d, 0x3f, sizeof d);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%c", &ch);
            s[i][j] = ch;
            if (ch >= 'a' && ch <= 'z')mp[ch - 'a'].push_back({i,j});
            else if (ch == 'S')x = i, y = j;
            else if (ch == 'G')resx = i, resy = j;
        }
        getchar();
    }

    queue q;
    q.push({ x,y });
    d[x][y] = 0;
    while (q.size()) {
        PII t = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            int a = t.first + dx[i], b = t.second + dy[i];

            if (a<1 || a>n || b<1 || b>m || s[a][b] == '#')continue;
            if (d[a][b] > d[t.first][t.second] + 1) {
                d[a][b] = d[t.first][t.second] + 1;
                q.push({ a,b });
            }
            if (s[a][b] == 'G')break;
            if (s[a][b] >= 'a' && s[a][b] <= 'z') {
                for (auto it : mp[s[a][b] - 'a']) {
                    if (it.first == a && it.second == b)continue;
                    if (d[it.first][it.second] > d[a][b] + 1) {
                        d[it.first][it.second] = d[a][b] + 1;
                        q.push({ it.first,it.second });
                    }
                    mp[s[a][b] - 'a'].clear();
                }
                
            }
        }
    }
    if (d[resx][resy] == 0x3f3f3f3f)printf("-1");
    else printf("%d", d[resx][resy]);

    return 0;
}

7-26 ICPC保定站

#include 
using namespace std;
typedef long long LL;
const int N = 50;
typedef pair PII;
int n, t, k;
int w[N];
LL weights[1 << 24], cnt = 0;
LL res;

void dfs1(int u, LL s) {
    if (u == k) {
        weights[cnt++] = s;
        return;
    }

    dfs1(u + 1, s);
    if (s + w[u] <= t)dfs1(u + 1, s + w[u]);
}

void dfs2(int u, LL s) {
    if (u == n) {
        int l = 0, r = cnt - 1;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (weights[mid] <= (LL)t - s)l = mid;
            else r = mid - 1;
        }
        if (weights[l] + s <= t)
            res = max(res, weights[l] + s);
        return;
    }

    dfs2(u + 1, s);
    if (w[u] + s <= t)dfs2(u + 1, s + w[u]);
}


int main()
{
    scanf("%d%d", &n, &t);
    for (int i = 0; i < n; i++)scanf("%d", &w[i]);

    sort(w, w + n);
    reverse(w, w + n);

    k = n / 2;

    dfs1(0, 0);

    sort(weights, weights + cnt);
    cnt = unique(weights, weights + cnt) - weights;
    dfs2(k, 0);

    cout << res;
    return 0;
}

7-27 简单的异或

#include 
#include 
#include 
#include 

using namespace std;

const int N = 300010;

int n, m;
int a[N], tr[N];

int lowbit(int x)
{
    return x & -x;
}

void add(int x, int v)
{
    for (int i = x; i <= n; i += lowbit(i)) tr[i] ^= v;
}

int query(int x)
{
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) res ^= tr[i];
    return res;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i <= n; i++) add(i, a[i]);

    while (m--)
    {
        int k, x, y;
        scanf("%d%d%d", &k, &x, &y);
        if (k == 2) printf("%d\n", query(y) ^ query(x - 1));
        else add(x, y);
    }

    return 0;
}

7-28 选我啊!

#include 
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
struct stu {
    LL a, b, c;
}st[N];

LL resa;
int n;
bool cmp(stu s1, stu s2) {
    return s1.c > s2.c;
}
int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d", &st[i].a, &st[i].b);
        resa += st[i].a;
        st[i].c = st[i].a * 2 + st[i].b;
    }
    sort(st, st + n, cmp);
    int res = 0;
    for (int i = 0; i < n; i++) {
        if (resa < 0)break;
        resa -= st[i].c;
        res++;
    }
    cout << res;

    return 0;
}

7-29 豪华酒店

#include 
using namespace std;
typedef long long LL;
const int N = 4e5+10;
int n,m;
int a,b,c;
struct node{
    int x;
    int money;
}s[N];
int cnt;
LL sum = 0;
LL res=0,pre = 0;
bool cmp(node n1,node n2){
    if(n1.x==n2.x)return n1.money>n2.money;
    return n1.x

7-30 摆放小球

#include 
using namespace std;
typedef long long LL;
const int N = 105;
int n, m, a, b, k;
int st[N];
pair f[N], s[N];
int sum = 0;
void dfs(int u) {
    if (u == k + 1) {
        int res = 0;
        for (int i = 1; i <= m; i++) {
            if (st[f[i].first]!=0 && st[f[i].second] != 0)res++;
        }
        sum = max(sum, res);
        return;
    }
    st[s[u].first]++;
    dfs(u + 1);
    st[s[u].first]--;

    st[s[u].second]++;
    dfs(u + 1);
    st[s[u].second]--;
}

int main()
{
    memset(st, 0, sizeof st);
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &a, &b);
        f[i].first = a, f[i].second = b;
    }
    scanf("%d", &k);
    for (int i = 1; i <= k; i++) {
        scanf("%d%d", &a, &b);
        s[i].first = a, s[i].second = b;
    }
    dfs(1);
    cout << sum;
    //if(a[n]==0)cout<<"Yes";
    //else cout<<"No";
    return 0;
}

7-31 最大公约数的和

#include
#define re register int
long long n, ans, f[4000010];
int main() {
    scanf("%lld", &n);
    for (re i = n; i; --i) {
        f[i] = n / i * (n / i);
        for (int j = i << 1; j <= n; j += i)f[i] -= f[j];
        ans += (f[i] * i - i)/2;
    }
    printf("%lld", ans);
    return 0;
}

7-32 一道简单题

#include 

using namespace std;
int n;


int main()
{
    cin >> n;
    map mp;
    for (int i = 0; i <= 30; i++) {
        for (int j = 0; j <= 30; j++) {
            if (i == j)continue;
            int x = (1 << i) + (1 << j);
            mp[x] = 1;
        }
    }
    int minn = 1e9 + 10;
    for (auto it : mp) {
        minn = min(minn, abs(it.first - n));
    }

    cout << minn;

    return 0;
}

7-33 一个无限大的集合

#include
using namespace std;
const int N = 1e6 + 10, mod = 998244353;
typedef long long LL;
int f[N];
int p;

int main() {
	f[1] = 1;
	LL res = 1;
	cin >> p;
	for (int i = 2; i <= p; i++) {
		f[i] = (f[i - 1] + f[i - 2]) % mod;
		res = (res + f[i]) % mod;
	}
	cout << res;
}

你可能感兴趣的:(贪心算法,算法,c++)