首页 > 其他分享 >2024-03-21

2024-03-21

时间:2024-03-21 21:22:07浏览次数:16  
标签:03 21 10 int ll 2024 ++ include bmod

2024-03-21

Grass Cownoisseur G

上周没写完的题

分析过思路了,直接放码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>

using namespace std;

const int N=100100,M=2*N;

int n,m;

int hd[N],edg[N],nxt[N],idx;

void adde(int u,int v) {
	edg[idx]=v,nxt[idx]=hd[u],hd[u]=idx++;
}

pair<int,int> es[N];

vector<int> G[M];

int scc[N],siz[M],cnt;
int dfn[N],low[N],idt;
int stk[N],top;
bool ins[N];

void Tarjan(int u) {
	dfn[u]=low[u]=++idt;
	stk[++top]=u,ins[u]=true;
	for(int i=hd[u];~i;i=nxt[i]) {
		int v=edg[i];
		if(!dfn[v]) {
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(ins[v]) low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u]) {
		cnt++;
		while(stk[top]!=u) {
			scc[stk[top]]=cnt;
			siz[cnt]++;
			ins[stk[top]]=false;
			top--;
		}
		scc[u]=cnt;
		siz[cnt]++;
		ins[u]=false;
		top--;
	}
}

int dist[M];
bool inq[M];

void spfa() {
	queue<int> que;
	que.push(scc[1]);
	inq[scc[1]]=true;
	while(!que.empty()) {
		int u=que.front();
		que.pop();
		inq[u]=false;
		for(int i=0;i<G[u].size();i++) {
			int v=G[u][i];
			if(dist[v]<dist[u]+siz[u]) {
				dist[v]=dist[u]+siz[u];
				if(!inq[v]) {
					que.push(v);
					inq[v]=true;
				}
			}
		}
	}
}

int main() {
	memset(hd,-1,sizeof(hd));
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		adde(u,v);
		es[i].first=u,es[i].second=v;
	}
	for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);
	for(int i=1;i<=cnt;i++) siz[i+cnt]=siz[i];
	for(int i=1;i<=m;i++) {
		int u=es[i].first,v=es[i].second;
		if(scc[u]==scc[v]) continue;
		G[scc[u]].push_back(scc[v]);
		G[scc[u]+cnt].push_back(scc[v]+cnt);
		G[scc[v]].push_back(scc[u]+cnt);
	}
	G[scc[1]].push_back(scc[1]+cnt);
	spfa();
	printf("%d\n",dist[scc[1]+cnt]);
	
	return 0;
} 

听课的时候老师讲的
终于知道 C++ 负数取模是负数的原因了
因为 C++ 整除是 向 0 取整 Python 等 是 向负无穷取整
意思就是 C++ 向靠近 0 的那边取整
eg:
C++: 5/3=1 -5/3=-1
Python: 5/3=1 -5/3=-2


说唱

上周考试不会的题,改改

首先理解 \(f(x)\) 是什么意思
例如 \(x=2134\) 那么 \(f(x)=2134+213+21+2\)
换一个形式 \(f(x)=2222+111+33+4\)
我们发现,对于从右往左数第 \(k\) 个数字 \(a_k\) 它对 \(f(x)\) 的贡献是

\[a_k\times\sum_{i=0}^{k-1}10^i \]

等比数列求和一下,其实就是

\[\frac{(10^k-1)\times a_k}{9} \]

把所有位的贡献加起来,得到

\[y=f(x)=\frac{10x-S}{9} \]

其中 \(S\) 是 \(x\) 所有位上数字之和
整理一下

\[10x-9y=S \]

我们记 \(p=10x\) 从第一个大于等于 \(9y\) 的 \(10\) 的倍数开始枚举 \(p\)
注意到 \(x\) 的数字之和就是 \(p\) 的数字之和
每次 \(p\) 加十的时候更新 \(S\) ,再记录 \(p-9y\) 为 \(D\)
若某一时刻 \(S\) 与 \(D\) 相等就得到答案
如果一直枚举到 \(D\) 比 n 位数字所能达到的最大的数字和 \(9n\) 还大都没有找到答案,说明无解

时间复杂度 \(O(n)\)

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=6e5+10;

char s[N];
int x[N],y[N];
int D;
int S;

int n;

int main() {
	int T;
	scanf("%d",&T);
	while(T--) {
		memset(x,0,sizeof(x));
		memset(y,0,sizeof(y));
		D=0,S=0;
		scanf("%s",s+1);
		n=strlen(s+1);
		int nn=n;
		for(int i=1;i<=n;i++) y[i]=s[n-i+1]-'0',x[i]=y[i]*9;
		if(nn==1&&y[1]==0) {
			puts("0");
			continue;
		}
		for(int i=1;i<=n;i++) x[i+1]+=x[i]/10,x[i]%=10;
		while(x[n+1]>9) x[n+2]+=x[++n]/10,x[n]%=10;
		n+=(x[n+1]>0);
		int p=1;
		D+=10-x[p],x[p]+=10-x[p];
		while(x[p]>9) x[p+1]+=x[p]/10,x[p]%=10,p++;
		n=max(n,p);
		for(int i=1;i<=n;i++) S+=x[i];
		bool flg=false;
		while(D<=9*nn) {
			if(S==D) {
				for(int i=n;i>1;i--) printf("%d",x[i]);
				puts("");
				flg=true;
				break; 
			}
			D+=10;
			int p=2;
			x[p]++;
			while(x[p]>9) x[p+1]+=x[p]/10,x[p]%=10,p++;
			n=max(n,p);
			S-=9*(p-2),S++;
		}
		if(!flg) puts("-1");
	}
	
	return 0;
}

ztx 的玄学方法(不知道正不正确)

  • 原题中的递归式如果不向下取整,y=x*10/9,则 x=y*0.9
  • 加上取整误差不超过 \(\log x\) 也就是位数 n
  • f(x) 单调增,可以二分

复杂度 \(O(n\log n)\)

扩展中国剩余定理

数学专题题单上面的
发现自己 72 分

update: 原因是要开 _int128……

exCRT

对于两个方程

\[\left\{\begin{matrix} x\equiv r_1 \ (\bmod \ p_1) \\ x\equiv r_2 \ (\bmod \ p_2) \end{matrix}\right. \]

考虑怎么合并
写成带余除法的形式

\[x=k_1\times p_1+r_1=k_2\times p_2+r_2 \]

移项得到

\[k_1\times p_1-k_2\times p_2=r_2-r_1 \]

用 exgcd 求出 k1 的最小正整数解
新的方程为

\[x\equiv R \ (\bmod \ M) \]

其中$$R=k_1\times p_1+r_1 \ \ \ M=lcm(p_1,p_2)$$

n个方程,两两合并 n-1 次
最后的 R 就是答案

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;
typedef __int128 i128;

int n;
ll pin,rin;

i128 exgcd(i128 a,i128 b,i128 &x,i128 &y) {
	if(b==0) {
		x=1,y=0;
		return a;
	}
	i128 d=exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return d;
}

int main() {
	scanf("%d",&n);
	scanf("%lld%lld",&pin,&rin);
	i128 p1=pin,r1=rin;
	for(int i=1;i<n;i++) {
		scanf("%lld%lld",&pin,&rin);
		i128 p2=pin,r2=rin;
		i128 k1,k2;
		i128 d=exgcd(p1,p2,k1,k2);
		i128 g=r2-r1;
		if(g%d!=0) {
			puts("-1");
			return 0;
		}
		k1=((k1*g/d)%(p2/d)+(p2/d))%(p2/d);
		r1+=p1*k1,p1=(p1*p2)/d;
	}
	printf("%lld\n",r1);
	
	return 0;
}

荒岛野人

原题等价于

给定 \(C_1,C_2,\dots,C_n \ \ \ P_1,P_2,\dots,P_n \ \ \ L_1,L_2,\dots,L_n\)
求最小的 M ,使得对于任意一对 \(i,j\) ,同余方程 \(C_i+xP_i\equiv C_j+xP_j \ (\bmod \ M)\) 都无解或最小正整数解大于 \(\min(L_i,L_j)\)
方程可以化为

\[(P_i-P_j)\times x\equiv C_j-C_i \pmod{M} \]

从 \(\max C_i\) 开始枚举 \(M\)

然后枚举所有的 \((i,j)\) 用 exgcd 求出最小的正整数解

如果有符合条件的解,那么当前的 M 不行
如果所有 \(n^2\) 个方程都在范围内无解,输出当前的 M

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=17;

int n;
int c[N],p[N],l[N];

int exgcd(int a,int b,int &x,int &y) {
	if(b==0) {
		x=1,y=0;
		return a;
	}     
	int d=exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return d;
}

bool check(int M) {
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++) {
			if(i==j) continue;
			if(p[i]<p[j]) continue;
			int A=p[i]-p[j],B=c[j]-c[i];
			int x,y;
			int d=exgcd(A,M,x,y);
			if(B%d==0) {
				x=((x*(B/d))%(M/d)+(M/d))%(M/d);
				if(x<=min(l[i],l[j])) return false;
			}
		}
	}
	return true;
}

int main() {
	scanf("%d",&n);
	int m=0;
	for(int i=1;i<=n;i++) scanf("%d%d%d",&c[i],&p[i],&l[i]),m=max(m,c[i]);
	while(true) {
		if(check(m)) {
			printf("%d\n",m);
			break;
		}
		m++;
	}
	
	return 0;
}

古代猪文

Lucas定理
若 p 是质数

\[{n\choose m} \bmod \ p={\left\lfloor n/p\right\rfloor\choose\left\lfloor m/p\right\rfloor}\times {n\bmod p\choose m\bmod p}\bmod p \]

# 题意简述 #
计算

\[g^{\sum_{k\mid n}{n\choose k}}\bmod 999911659 \]

# Solution #

数学全家桶
欧拉定理 + 卢卡斯定理 + 中国剩余定理 + 快速幂

  • \(999911659\) 是质数 根据欧拉定理 就是要算 \(g^{\sum_{k\mid n}{n\choose k}\bmod 999911658}\bmod 999911659\)

考虑如何计算 \(\sum_{k\mid n}{n\choose k}\bmod 999911658\)

  • \(999911658=2\times3\times4679\times35617\)

有些题的模数比较奇怪的时候可以分解一下看看可能会有特殊性质

  • Lucas 求出 \(\sum_{k\mid n}{n\choose k}\) 模每个小质数的结果 \(r_i\)

  • 然后中国剩余定理求解同余方程组

\[\left\{\begin{matrix} x\equiv r_1\pmod2\\ x\equiv r_2\pmod3\\ \ \ \ \ \ \ x\equiv r_3\pmod{4679}\\ \ \ \ \ \ \ \ \ x\equiv r_4\pmod{35617} \end{matrix}\right. \]

得出 \(\sum_{k\mid n}{n\choose k}\bmod 999911658\)

  • 最后快速幂就行
#include<iostream>
#include<cstring>
#include<algorithm>

#define mod 999911658

using namespace std;

typedef long long ll;

const int dd[4]={2,3,4679,35617};

ll n,g;

ll frac[99999];

ll qpow(ll a,ll k,ll p) {
	ll res=1;
	while(k) {
		if(k&1) res=res*a%p;
		a=a*a%p,k>>=1;
	}
	return res;
}

ll C(ll x,ll y,ll p) {
	if(x<y) return 0;
	return frac[x]*qpow(frac[y],p-2,p)%p*qpow(frac[x-y],p-2,p)%p;
}

ll Lucas(ll x,ll y,ll p) {
	if(y==0) return 1;
	return C(x%p,y%p,p)*Lucas(x/p,y/p,p)%p;
}

void init(ll x) {
	frac[0]=1;
	for(ll i=1;i<=x;i++) frac[i]=frac[i-1]*i%x;
}

int r[5];

int main() {
	scanf("%lld%lld",&n,&g);
	if(g%(mod+1)==0) {
		puts("0");
		return 0;
	}
	ll h=0;
	for(int i=0;i<4;i++) {
		ll D=dd[i];
		init(D);
		for(ll d=1;d*d<=n;d++) {
			if(n%d!=0) continue;
			r[i]=(r[i]+Lucas(n,d,D))%D;
			if(d*d==n) continue;
			r[i]=(r[i]+Lucas(n,n/d,D))%D;
		}
		h=(h+r[i]*(mod/D)%mod*qpow(mod/D,D-2,D)%mod)%mod;
	}
	printf("%lld\n",qpow(g,h,mod+1));
	
	return 0;
}

需要注意的点:

  1. 组合数 C(n,m) 在 n<m 的时候要返回 0(不然会RE)
  2. g 是模数的倍数的时候特判输出 0
  3. frac 不能 一开始初始化,各个函数的模数也不能用全局的,而是要传参数,因为 4 个模数情况都不一样要单独考虑

标签:03,21,10,int,ll,2024,++,include,bmod
From: https://www.cnblogs.com/Orange-Star/p/18086782

相关文章

  • 2024年天梯成信校赛补题
    1-1代码胜于雄辩嘿嘿 L1-2收水费思路:分类讨论 L1-3日期思路:模拟 L1-4回文数思路:翻转后判断是否相等 L1-5yihan的新函数思路:模拟 L1-6二进制思路:二进制每位最多进位1,模拟下二进制加法即可 L1-7大山中的学院思路:统计每个山脉对空地的贡献 L1-8堆积木思......
  • 3.21
    给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。代码packageorg.example;importjava.util.Scanner;publicclassShuzu......
  • 2024年3月21日-发射子弹
    创建组件子弹,然后挂上材质发光之后,然后给子弹加逻辑,选中自带模型角色新建图表→设置按1发射→输入从类然后选择spawnactorfromclass选择刚才设置的子弹然后点spawntransform,进行发射点设置,选择分割  把碰撞设置改成不碰撞输入self,然后输入位置,获取自身位置......
  • 20240321打卡
    第四周第一天第二天第三天第四天第五天第六天第七天所花时间1h5h3h1.5h代码量(行)212359274547博客量(篇)1111知识点了解Kotlin编写用户注册与登录功能jetpack的深入使用hilt依赖注入与kotlin协程等知识了解蓝桥杯题目练习......
  • 20240321每日一题题解
    20240321每日一题题解Problem已知\(f(x,n)=\sqrt{n+\sqrt{(n-1)+\sqrt{(n-2)+\sqrt{...+2+\sqrt{1+x}}}}}\)。计算\(f\)的值。输入\(x\)和\(n\)​。输出这个函数值,并且注意需要保留两位小数。例如,输入4.210,则应该输出3.68Solution递归?循环?说实话这道题是有一定思考......
  • BEE1038:经济学数据科学导论
    BEE1038:经济学数据科学导论在这项任务中,你将展示你对编程的理解和掌握Python使用数据科学工具。到第6/7周结束时,你将学到的东西几乎涵盖了你所需要的一切,你所学到的已经足够着手解决一些问题了。如果你被卡住了再读一遍笔记本。如果你仍然不确定,那就上网看看。谷歌和StackOverFl......
  • 代码随想录算法训练营第五十三天 | 53. 最大子序和 动态规划,1035.不相交的线,1143.最
    53.最大子数组和 已解答中等 相关标签相关企业 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。  示例1:输入:nums=[-2,1,-3,4,-1,2,1,-5,4]......
  • 3.21
     第十二天所花时间3h代码量150行博客量1篇所学的知识完成学习记录的制作     <?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.......
  • Cinema 4D 2024.1(C4D2024)安装包下载及安装教程
    下载链接:https://docs.qq.com/doc/DTE5lQ2RmR2JKWk5w1.双击进行解压,点击“开始”2.选中“MaxonCINEMA4DStudio2024.1.exe”右键以管理员身份运行3.点击“前进”4.选择安装路径,点击“前进”(建议和我的安装路径保持一致)5.软件正在安装中,请耐心等待安装完成......
  • 【IEEE会议征稿】第七届计算机信息科学与应用技术国际学术会议(CISAT 2024)
    【IEEE出版】第七届计算机信息科学与应用技术国际学术会议(CISAT2024)20247th InternationalConferenceonComputerInformationScience andApplicationTechnology 第七届计算机信息科学与应用技术国际学术会议(CISAT2024)定于2024年7月12-14日在中国杭州召开,会议由浙......