A层1

Pseudo-Random Number Generator

分段打表 + 找循环节

找循环节的过程很有意思

打表
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const ull mod = 1ull << 40;
const ull s0 = 0x600DCAFE;
const int maxn = 10000005;
int main(){
	ull p1 = s0, p2 = s0;
	p1 = (p1 + (p1 >> 20) + 12345) % mod;
	p2 = (p2 + (p2 >> 20) + 12345) % mod;
	p2 = (p2 + (p2 >> 20) + 12345) % mod;
	ull cnt, len;
	for(cnt = 1; p1 != p2; ++cnt){
		p1 = (p1 + (p1 >> 20) + 12345) % mod;
		p2 = (p2 + (p2 >> 20) + 12345) % mod;
		p2 = (p2 + (p2 >> 20) + 12345) % mod;
	}
	printf("%llu\n",cnt);
	p2 = (p2 + (p2 >> 20) + 12345) % mod;
	for(len = 1; p1 != p2; ++len)
		p2 = (p2 + (p2 >> 20) + 12345) % mod;
	printf("%llu %llu\n", cnt, len);
	p1 = s0; for(int i = 1; i <= len; ++i)p1 = (p1 + (p1 >> 20) + 12345) % mod;
	p2 = s0;
	ull first = 0;
	for(first = 0; p1 != p2; ++first){
		p1 = (p1 + (p1 >> 20) + 12345) % mod;
		p2 = (p2 + (p2 >> 20) + 12345) % mod;
	}
	printf("%llu\n\n\n",first);
	// printf("%llu\n",ans);
	// ull ans = 1; 
	p1 = s0;
	for(ull now = 1; now <= first; ++now){
		p1 = (p1 + (p1 >> 20) + 12345) % mod;
	// 	ans += 1 - (p1 & 1);
	// 	// if(now % 10000000 == 0)printf("%llu %llu\n",p1,ans);
	// 	if(now % 10000000 == 0)printf("%llu,",p1);
	}
	// printf("\n");
	// printf("\n");
	// printf("\n");

	// printf("%llu,",p1);
	// ull las = ans;
	ull ans = 0;
	printf("\n");
	// printf("%llu %llu\n",p1, ans);
	for(ull now = first; now <= first + len; ++now){
		if((now - first) % 10000000 == 0)printf("%llu,", p1);
		ans += 1 - (p1 & 1);
		p1 = (p1 + (p1 >> 20) + 12345) % mod;
	}
	// printf("%llu %llu\n",p1, ans);
	// printf("%llu,",ans - las);
	return 0;
}


code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const ull mod = 1ull << 40;
const ull s0 = 0x600DCAFE;
const ull fir = 350125310;
const ull len = 182129209;
const ull each = 91029304;
const ull base = 10000000;
const ull p0 = 516914;
ull a1[105] = {1, 5004364,10006017,15011683,20012408,25031296,30040232,35042602,40042828,45056959,50056831,55056278,60057168,65062411,70077204,75074286,80089334,85076566,90060817,95067617,100089173,105080524,110081437,115071718,120091493,125100277,130104566,135114812,140110603,145118771,150119937,155117508,160106698,165108248,170101751,175085228};
ull p1[105] = {s0,14370630249,38312556854,83248007737,167560289742,325792323073,622741727028,937685173,13107744445,35943646365,78802032994,159235062884,310147760736,593348380684,295498034,11901289737,33681877906,74557367833,151258698876,295206930517,565345893787,1072246754882,10752858133,31526697331,70512631458,143677078963,280954761586,538598461112,1022070324749,9655697881,29466792348,66642984633,136417233148,267368060404,513107125545,974225187667};
ull a2[105] = {1,4989280,9983340,14984746,19988258,24980216,29971111,34971436,39962817,44967154,49973217,54964748,59985790,64989687,69988721,74980113,79977390,84979857,89965024};
ull p2[105] = {516914,11347508705,32642538921,72602179030,147587596515,288299158592,552368730897,1047889963499,10220465107,30528085091,68635277779,140147868236,274358548202,526208585828,998852854893,9149398605,28517124738,64866088952,133077482701};
ull ans;
void noloop(ull x){
	ans += a1[x / base];
	ull p = p1[x / base];
	x %= base;
	for(int i = 1; i <= x; ++i){
		p = (p + (p >> 20) + 12345) % mod;
		ans += 1 - (p & 1);
	}
}
int main(){
	ull n; scanf("%llu",&n);
	if(n == 0){
		printf("0\n");
		return 0;
	}
	--n;
	noloop(min(n, fir - 1));
	if(n > fir){
		n -= fir;
		ans = ans + each * (n / len);
		n %= len;
		ans = ans + a2[n / base];
		ull p = p2[n / base];
		n %= base;
		for(int i = 1; i <= n; ++i){
			p = (p + (p >> 20) + 12345) % mod;
			ans += 1 - (p & 1);
		}
	}
	printf("%llu\n",ans);
	return 0;
}

Counting Trees

找区间最小值个数,乘上卡特兰数对应项,然后用最小值把区间分成若干段

code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int maxn = 2000005;
const int mod = 1000000007;
int fac[maxn], inv[maxn], v[maxn], l[maxn], ans = 1;
int qpow(int x, int y){
	int ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
	return ans;
}
int c(int n, int m){if(m > n || n < 1 || m < 1)return 1;return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;}
int ctl(int n){if(n < 1)return 1;return (0ll + mod + c(n + n, n) - c(n + n, n + 1)) % mod;}
int n;
struct node{int mi, pos;};
struct tree{
	node t[maxn << 2 | 1];
	void push_up(int x){
		if(t[x << 1].mi <= t[x << 1 | 1].mi){
			t[x].mi = t[x << 1].mi;
			t[x].pos = t[x << 1].pos;
		}else{
			t[x].mi = t[x << 1 | 1].mi;
			t[x].pos = t[x << 1 | 1].pos;
		}
	}
	void built(int x, int l, int r){
		if(l == r){
			t[x].mi = v[l]; t[x].pos = l;
			return;
		}
		int mid = (l + r) >> 1;
		built(x << 1, l, mid);
		built(x << 1 | 1, mid + 1, r);
		push_up(x);
	}
	node query(int x, int l, int r, int L, int R){
		if(L <= l && r <= R)return t[x];
		int mid = (l + r) >> 1;
		node ans; ans.mi = maxn;
		if(L <= mid)ans = query(x << 1, l, mid, L, R);
		if(R > mid){
			node p = query(x << 1 | 1, mid + 1, r, L, R);
			if(p.mi < ans.mi)ans = p;
		}
		return ans;
	}
}t;
int nxt[maxn], vp[maxn];
void solve(int l, int r){
	if(l >= r)return;
	node nw = t.query(1, 1, n, l, r);
	int las = l - 1, now = nw.pos, cnt = 0;
	for(; now <= r && now; now = nxt[now]){
		solve(las + 1, now - 1);
		las = now; ++cnt;
	}
	if(las >= l && las < r)solve(las + 1, r);
	// printf("%d %d %d %d %d\n",l, r, cnt,nw.mi, nw.pos);
	ans = 1ll * ans * ctl(cnt) % mod;
}
int main(){
	scanf("%d", &n);
	if(n == 0){
		printf("1\n");
		return 0;
	}
	fac[0] = 1; for(int i = 1; i <= maxn - 2; ++i)fac[i] = 1ll * fac[i - 1] * i % mod;
	inv[maxn - 2] = qpow(fac[maxn - 2], mod - 2); for(int i = maxn - 3; i > 0; --i)inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
	inv[0] = 1;
	for(int i = 1; i <= n; ++i)scanf("%d",&v[i]);
	for(int i = 1; i <= n; ++i)l[i] = v[i];
	sort(l + 1, l + n + 1); int cnt = unique(l + 1, l + n + 1) - l - 1;
	for(int i = 1; i <= n; ++i)v[i] = lower_bound(l + 1, l + cnt + 1, v[i]) - l;
	t.built(1, 1, n);
	for(int i = n; i; --i){
		nxt[i] = vp[v[i]];
		vp[v[i]] = i;
	}
	solve(1, n);
	printf("%d\n",ans);
	return 0;
}
posted @   Chen_jr  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示