河南萌新聯賽2024第(一)場 補題報告

羽原圆华發表於2024-07-18

小藍的二進位制詢問

image


找規律,可以發現 把從0開始的十進位制數字轉化為二進位制。每一個二進位制位有0或1兩種狀態。從低到高的第一位以2為週期,第二位以4為週期,第三位以8為週期……也就是說第n位以 2^{n} 為週期。每個週期都是前一半是0,後一半是1 。


舉例:
000 001 010 011 100 ……

#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int N=100;
long long f[N][N];
int a[N];
int k;
int mod = 998244353;
int c;
int ans = 0;
int get(int x)   //計算x的二進位制長度
{
	int cnt = 0;
	while(x)
	{
		x/=2;
		cnt++;
	}
	return cnt;
}
int solve(long long x)
{
	ans = 0 ;
    int cnt = get(x);
    x++;     //因為週期是從0開始算的

    for(int i=1;i<=cnt;i++)
    {
    	int tt = pow(2,i);      //第i位的週期
    	ans += (x/tt)*(tt/2);   //0~x 第i位1的個數
    	ans %= mod;
    	ans += max(0ll,x%tt-tt/2);  //週期內仔細判斷
    	ans %= mod;
    }
    return ans;
}

signed main()
{
    int t, l, r;
    cin >> t;
    while(t--)
    {
        cin >> l >> r;
        int ans = (solve(r) - solve(l-1)+mod) % mod;    //差分求區間
        cout << ans << endl;
    }
    return 0;
}

旅途的終點


注意!是按既定的路線旅遊的!所以不能簡單地透過排序找出k個最大的點。
正解:維護一個元素從小到大的大小為k的優先佇列,從1~n按順序放入數。當佇列滿時,從隊首彈出最小的元素,放入接下來的元素。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int ddx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int ddy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int INF=0x3f3f3f3f;
const int N=6e5+10;
int n,m,k;
int a[N];
int sum = 0;
void solve()
{
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	priority_queue<int,vector<int>,greater<int>>q;
	for(int i=1;i<=n;i++)
	{
		q.push(a[i]);
		if(q.size()>k)
		{
			sum+=q.top();
			q.pop();
		}
		if(sum>=m)
		{
			cout<<i-1<<endl;
			return;
		}
	}
	cout<<n<<endl;
	return;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t=1;
    //cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

相關文章