一些思维题(持续更新)

AtCoder Regular Round 152 A - Seat Occupation

思路:

最坏的情况是第一次来的组从第二个位开始坐,此后每次来的组都与前一组空一个位,如果来的是一个人怎样都能坐下,只有一组两个人的情况会坐不下,我们用一个ans维护剩余的连续座位。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;

int main() {
	int n, t;
	bool flag = 1;
	cin >> n >> t;
	int a, ans = t;
	for (int i = 0; i < n; ++i) {
		cin >> a;
		if (a == 2 && ans < 2) {
			flag = 0;
		}
		ans -= (a + 1);
	}
	if (flag)
		cout << "Yes\n";
	else
		cout << "No\n";
	return 0;
}

SDNUOJ1263_约瑟夫环递归解法

思路:

很像数学归纳法的递归问题。找出f(n-1,m)和f(n,m)间的关系。

#include <bits/stdc++.h>
using namespace std;

int f(int n) {
	return n == 1 ? n : (f(n - 1) + 2) % n + 1;
}
//old=(new+m-1)%n+1
//不是old = (new + m ) % n 的原因是编号是从1开始的


int main() {
	int n;
	cin >> n;
	int ans = f(n);
	cout << ans << '\n';
	return 0;
}

牛客小白月赛63 E

思路:

先去掉1和n,把剩下n-2个数全排列。然后把1和n和 [ 和 ] 这四个点插进去,跟插板不一样的是,这个插法可以是一个空里插好几个板。我们始终让插进去的最左最右作为 [ , ] ,中间两个是1和n,可以颠倒顺序。所以最终的结果是A(n-2,n-2)*C(n-2+1+3,4)*2。

#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll

void work(){
    int n;
    cin>>n;
	if(n<=2){
        cout<<n<<'\n';return;
    }
    ll ans=2;
    for(int i=3;i<=n;++i){
        ans=ans*(i+2)%998244353;
    }
    cout<<ans<<'\n';
}

signed main() {
    io;
	work();
	return 0;
}

牛客2022跨年-C

C-翻卡牌_牛客2022跨年场 (nowcoder.com)

思路:

1e9+1%7=0

(x+1e9*x)%7=0。

#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;

void work() {
    string a;cin>>a;
    cout<<"0\n";
}

signed main() {
	io;
    work();
	return 0;
}

牛客2022跨年H

H-nana吃蛋糕_牛客2022跨年场 (nowcoder.com)

思路:

n为奇数,易知最大值为所有格之和。

偶数时,至少放弃一个i,j不同奇偶的格子。(其实没太看懂题解但是试了试确实是这样

#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define inf 0x3f3f3f3f3f3f3f3f
void work() {
    int n;cin>>n;
    int sum=0,minn=inf;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            int a;cin>>a;
            sum+=a;
            if((i+j)%2!=0){
                minn=min(minn,a);
            }
        }
    }
    if(n%2!=0){
        cout<<sum<<'\n';return;
    }else{
        cout<<sum-minn<<'\n';
    }
}

signed main() {
	io;
	work();
	return 0;
}

牛客小白月赛67E

E-游戏的买_牛客小白月赛67 (nowcoder.com)

思路:

答辩题意。想清楚对于每一天如何确定买还是不买,就速通这题了。

首先要明白今天是知道今天的价钱的,但是不知道以后的价钱。

逆推,最后一天必须买的期望易得是1/2a+1/2b,倒数第二天买不买呢,看期望,如果期望比ab都大那就必须今天买,如果期望比ab都小那今天一定不买,如果期望在ab之间,我们就去等倒数第二天出价,如果出的是小价钱就买,如果是大的就后面买,所以对于之前的天数来说倒数第二天的期望是1/2*min(a,b)+1/2*f[n]。

#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
//#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 3e5 + 50;
//__builtin_ctzll(x);后导0的个数
//__builtin_popcount计算二进制中1的个数
int a[N],b[N];
double f[N];

void work() {
    int n;cin>>n;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }for(int i=1;i<=n;++i){
        cin>>b[i];
    }
    f[n]=0.5*a[n]+0.5*b[n];
    for(int i=n-1;i>0;--i){
        if(f[i+1]>max(a[i],b[i]))f[i]=0.5*a[i]+0.5*b[i];
        else if(f[i+1]<min(a[i],b[i]))f[i]=f[i+1];
        else f[i]=0.5*f[i+1]+0.5*min(a[i],b[i]);
    }
    printf("%.15lf\n",f[1]);
}

signed main() {
	io;
	int t;
	cin >> t;
	while (t--) {
		work();
	}
	return 0;
}

 Problem - D - Codeforces

思路:

数学。

快速枚举n!质因数:对于某一个素数p,在n中,有一个质因数的数有p/n个,有两个的有p/n^2,以此类推,这样的时间是log的。

我写的好像不太好,用了4遍的东西我没写函数,但其实优化不了太多(。

#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
//#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 1e7 + 50;
const int M = 1e6 + 50;
//__builtin_ctzll(x);后导0的个数
//__builtin_popcount计算二进制中1的个数
bool is[N];
int tot;
int prime[N];

void euler_sieve() {
	tot = 0;
	for (int i = 2; i < N; ++i) {
		if (!is[i])
			prime[tot++] = i;//0为素数
		for (int j = 0; j < tot && prime[j]*i < N; ++j) {
			is[prime[j]*i] = 1;
			if (i % prime[j] == 0)
				break;
		}
	}
}

void work() {
	int l1, r1, l2, r2;
	cin >> l1 >> r1 >> l2 >> r2;

	int n = max(r1, r2);
	for (int i = 0; prime[i] <= n; ++i) {
		ll t = prime[i];
		if (t == 0)
			break;
		ll a = 0, b = 0, c = 0, d = 0;
		while (t <= n) {
			a += (l1 - 1) / t;
			b += r1 / t;
			c += (l2 - 1) / t;
			d += r2 / t;
			t *= prime[i];
		}
		if (b - a > d - c) {
			cout << "No\n";
			return;
		}
	}
	cout << "Yes\n";
}

signed main() {
	io;
	int t;
	cin >> t;
	euler_sieve();
	while (t--) {
		work();
	}
	return 0;
}

C-小菲爱数数_中国石油大学(北京)第三届“骏码杯”程序设计竞赛(同步赛) (nowcoder.com)

算贡献。

思路:

计算每个因子的贡献。st记录每个因子上次出现的位置。

对于第i位数的一个因子x,他首先有i-st[x]份的贡献是与之前的数组合的,在之后的位数里,如果未出现x,那么now中已经有i-st[x]份属于他的贡献了,每位数都加一个now即每一位都有一个i-st[x]的贡献,直到遇到下一个含x因子的位数重复操作。

#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define i64 __int64
//#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 1e6 + 50;
//__builtin_ctzll(x);后导0的个数
//__builtin_popcount计算二进制中1的个数
int a[N];
int st[N];
ll now=0,res=0;

void work() {
    int n;cin>>n;
    vector<int>p;
    now=0;res=0;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        int x=a[i];
        for(int j=2;j*j<=x;++j){
            if(x%j==0){
                if(!st[j])p.pb(j);
                now+=i-st[j];
                while(x%j==0)x/=j;
                st[j]=i;
            }
        }
        if(x!=1){
            if(!st[x])p.pb(x);
            now+=i-st[x];
            st[x]=i;
        }
        res+=now;
    }
    cout<<res<<'\n';
    for(auto x:p){
        st[x]=0;
    }
}

signed main() {
	io;
	int t;
	cin >> t;
	while (t--) {
		work();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值