IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> SCOI2010 -> 正文阅读

[C++知识库]SCOI2010

生成字符串

这题实际是数论?可以考虑把 1 1 1 的个数和 0 0 0 的个数的和看做 x x x,差看做 y y y,那向右上走表示选择 1 1 1 ,向右下走表示选择 0 0 0,这道题就表示为从 ( 0 , 0 ) (0,0) (0,0) 走到 ( n + m , n ? m ) (n+m,n-m) (n+m,n?m),其中 m m m 步选择向右下走,总方案数即为 C n + m m \mathrm{C}_{n+m}^m Cn+mm?,那么考虑限制条件,经过 y = ? 1 y=-1 y=?1 的方案就是 1 1 1 0 0 0 少的方案,而根据对称性,从 ( 0 , 0 ) (0,0) (0,0) 经过 y = ? 1 y=-1 y=?1 ( n + m , n ? m ) (n+m,n-m) (n+m,n?m) 相当于从 ( ? 2 , 0 ) (-2,0) (?2,0) 走到 ( n + m , n ? m ) (n+m,n-m) (n+m,n?m)。这个方案数即为 C n + m m ? 1 \mathrm{C}_{n+m}^{m-1} Cn+mm?1? ,所以答案即为
C n + m m ? C n + m m ? 1 \mathrm{C}_{n+m}^m-\mathrm{C}_{n+m}^{m-1} Cn+mm??Cn+mm?1?,组合数可以用逆元搞定。

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5,p=20100403;
int n,m,jc[N],ni[N];
int qpow(int a,int b){
    int ret=1;
    while(b){
        if(b&1) ret=1ll*ret*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return ret;
}
int C(int x, int y) {
    int z=1ll*jc[x]*ni[y]%p;
    return 1ll*z*ni[x-y]%p;
}
int main() {
    jc[0]=1;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+m;i++) jc[i]=1ll*jc[i-1]*i%p;
    ni[n+m]=qpow(jc[n+m],p-2);
    for(int i=n+m-1;i>=0;i--)
        ni[i]=1ll*ni[i+1]*(i+1)%p;
    return printf("%d\n",(C(n+m,m)-C(n+m,m-1)+p)%p),0;
}

序列操作

更新中。。。(haibuhui)

连续攻击游戏

不多说了,看代码。

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x){
    T ch=getchar();x=0;
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
}
template<typename T>inline void prt(T x){
    if(x>9) prt(x/10);
    putchar(x%10|48);
}
int a,b;
int n;
bool c[10005];
int main(){
    read(n);
    for(int i=1;i<=n;++i){
        read(a),read(b);
        if(b<a) a^=b,b^=a,a^=b;
        if(c[a]) c[b]=1;
        else c[a]=1;
    }
    for(int i=1;i<=10001;++i)
        if(!c[i]){
            prt(i-1);
            return 0;
        }
}

传送带

明显这题的最优路线应是 A E + E F + F D AE+EF+FD AE+EF+FD,其中 E E E A B AB AB 上, F F F C D CD CD 上。设 F ( X , Y ) F(X,Y) F(X,Y) X X X Y Y Y 的距离。答案就是 A E P + E F R + F D Q \frac{AE}P+\frac{EF}R+\frac{FD}Q PAE?+REF?+QFD?这个方程有两个未知数,不好求最小值。不妨假设其中一个已知(这里为 E E E),那对于 F D FD FD 而言只要求出一个满足 E F R + F D Q \frac{EF}R+\frac{FD}Q REF?+QFD? 最小的值就行了。
不妨设 F D FD FD x x x,我们很明显可以根据 C C C D D D 的坐标求出 F F F 的坐标,都是一个 x x x 带点系数和常数,最终的式子是一个关于 x x x 的单峰函数(可以自己解解),那对于单峰函数,我们三分就可以求出最优的 F D FD FD。既然 F D FD FD 都三分了,为什么 A E AE AE 不一起三分呢 ? 综上此题是一个三分套三分
但其实我这道题不是三分做的所以待会没有三分代码,我想的是,既然只有 A E , F D AE,FD AE,FD 两个变量,为什么不暴力枚举呢?所以我的做法是暴力枚举 A E , F D AE,FD AE,FD 的长度,虽然分少了可能精度不够,分多了可能会 T L E TLE TLE,但我分了 3500 3500 3500 份就 A C AC AC 了。
暴力代码

#include<bits/stdc++.h>
using namespace std;
#define Re register
int Ax,Ay,Bx,By,Cx,Cy,Dx,Dy,P,Q,R;
double Ex,Ey,Fx,Fy;
double Lab,Lcd,mab,mcd;
double Xab,Yab,Xcd,Ycd;
double ans=9999999.9;
inline double dis(double A,double B,double C,double D){
	return sqrt((A-C)*(A-C)+(B-D)*(B-D));
}
inline double get(double i,double j){
	Ex=i*Xab+Ax;
	Ey=i*Yab+Ay;
	Fx=j*Xcd+Dx;
	Fy=j*Ycd+Dy;
	return sqrt(i*Xab*i*Xab+i*Yab*i*Yab)/P+dis(Ex,Ey,Fx,Fy)/R+sqrt(j*Xcd*j*Xcd+j*Ycd*j*Ycd)/Q;
}
int main(){
//	freopen("tran.in","r",stdin);
//	freopen("tran.out","w",stdout);
	scanf("%d%d%d%d%d%d%d%d%d%d%d",&Ax,&Ay,&Bx,&By,&Cx,&Cy,&Dx,&Dy,&P,&Q,&R);
	Xab=(Bx-Ax),Xcd=(Cx-Dx);
	Yab=(By-Ay),Ycd=(Cy-Dy);
	mab=1.0/3500.0,mcd=1.0/3500.0;
	for(Re int i=0;i<=3500;i++)
		for(Re int j=0;j<=3500;j++)
			ans=min(ans,get(i*mab,j*mcd));
//	find(1079);
	printf("%.2lf",ans);
}

幸运数字

思路很简单,得到所有的合法数字,然后容斥。即 ∑ i = 1 n ? R x i ? ? ∑ 1 ≤ i < j < n ? R l c m ( x i , x j ) ? + ∑ 1 ≤ i < j < k < n ? R l c m ( x i , x j , x k ) ? ? ? + ( ? 1 ) n + 1 ∑ ? R l c m ( x i , x j ? x n ) ? \sum_{i=1}^{n} \left \lceil \frac R{x_i} \right \rceil-\sum_{1\leq i<j<n} \left \lceil \frac R{lcm(x_i,x_j)} \right \rceil+\sum_{1\leq i<j<k<n} \left \lceil \frac R{lcm(x_i,x_j,x_k)} \right \rceil-\cdots+(-1)^{n+1}\sum\left \lceil \frac R{lcm(x_i,x_j\cdots x_n)} \right \rceil i=1n??xi?R???1i<j<n??lcm(xi?,xj?)R??+1i<j<k<n??lcm(xi?,xj?,xk?)R????+(?1)n+1?lcm(xi?,xj??xn?)R?? 但直接爆搜肯定是不行的,我们需要加yi点点小剪枝。

  1. 对于 6 6 6 66 66 66,这种情况, 66 66 66 肯定没有作用,可以删去。
  2. 从最大的合法数字倒着来,更快超出 R R R 的范围。

其它关于确定合法数字之类的详见代码。

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x){
	T ch=getchar();x=0;
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
}
template<typename T>inline void prt(T x){
	if(x>9) prt(x/10);
	putchar(x%10|48);
}
#define ll long long
ll a,b,ans,n;
ll p[3005],cnt=-1;
ll gcd(ll x,ll y){return y==0 ? x:gcd(y,x%y);}
void mak(ll x){
	if(x>b) return ;
	p[++cnt]=x;
	mak((x<<3)+(x<<1)+6);
	mak((x<<3)+(x<<1)+8);
}
void dfs(int x,ll lcm,int num){
	if(x>n){
		if(lcm!=1){
			if(num&1) ans+=((b/lcm)-(a/lcm));
			else ans-=((b/lcm)-(a/lcm));
		}
		return ;
	}
	dfs(x+1,lcm,num);
	ll d=p[x]/gcd(p[x],lcm);
	if(lcm<=b/d) dfs(x+1,lcm*d,num+1);
	return ;
}
signed main(){
	scanf("%lld%lld",&a,&b);a--;
	mak(0);
	sort(p+1,p+cnt+1);
	n=cnt;
	for(int i=1;i<=cnt;++i)
		for(int j=1;j<i;++j)
			if(p[i]%p[j]==0) {p[i]=9999999997,n--;break;}
	sort(p+1,p+cnt+1);
	reverse(p+1,p+n+1);
	dfs(1,1,0);
	prt(ans);
	return 0;
}

股票交易

读完题后,应该很容易想到用动态规划来解。设 F [ i , j ] F[i,j] F[i,j] 表示第 i i i 天手上有 j j j 张股票能赚多少钱,考虑转移。

  1. 凭空买,与前面的没有关系,同时也是状态的初值, 其它赋值为无穷小, F [ i , j ] = ? a p i ? j ( 0 ≤ j ≤ a s i ) F[i,j]=-ap_i*j(0\leq j\leq as_i) F[i,j]=?api??j(0jasi?)
  2. 不做买卖 F [ i , j ] = m a x ( F [ i , j ] , F [ i ? 1 , j ] ) F[i,j]=max(F[i,j],F[i-1,j]) F[i,j]=max(F[i,j],F[i?1,j])
  3. 做买卖,这是本题的主要问题,此处以买为例。
    题上虽说至少要隔 w w w 天,那是哪一天呢?其实就是第 i ? w ? 1 i-w-1 i?w?1 天,因为前面即使更优,也从情况 2:不做买卖转移到了第 i ? w ? 1 i-w-1 i?w?1 天,这样可以省掉一个 f o r for for 循环。
    接下来,我们不妨设第 i ? w ? 1 i-w-1 i?w?1 天手上有 k k k 张,要转移到 F [ i , j ] F[i,j] F[i,j] (因为是买 k k k 肯定小于 j j j)。可得方程:
    F [ i , j ] = max ? ( F [ i , j ] , F [ i ? w ? 1 , k ] ? ( j ? k ) × a p i ) F[i,j]=\max(F[i,j],F[i-w-1,k]-(j-k)\times ap_i) F[i,j]=max(F[i,j],F[i?w?1,k]?(j?k)×api?)
    但这样 O ( n m 2 ) O(nm^2) O(nm2) 肯定要 T L E TLE TLE 怎么办呢?我们不妨将上式拆了 F [ i , j ] = max ? ( F [ i , j ] , F [ i ? w ? 1 , k ] + k × a p i ) ? j × a p i F[i,j]=\max(F[i,j],F[i-w-1,k]+k\times ap_i)-j\times ap_i F[i,j]=max(F[i,j],F[i?w?1,k]+k×api?)?j×api?可以发现,对于所有的 j j j 来说, F [ i ? w ? 1 , k ] + k × a p i F[i-w-1,k]+k\times ap_i F[i?w?1,k]+k×api? 这一部分是不变的,而当 k k k 在变化时, ? j × a p i -j\times ap_i ?j×api? 也是不变的。这不就是滑动窗口吗?接着将单调队列的解法套上去就行了。关于单调队列详见代码注释。
    最后对于买来说, j j j 应该顺序,对于卖 j j j 应该逆序。
#include<bits/stdc++.h>
using namespace std;
template<typename W>inline void read(W &x){
	W ch=getchar(),tx=1;x=0;
	while(!isdigit(ch)) tx=ch=='-'?-1:tx,ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	x=tx*x;
}
int n,m,w,ap,bp,as,bs,ans,f[2001][2001];
int l,r,q[2001];
int main(){
	read(n),read(m),read(w);
	memset(f,0xcf,sizeof f);
	for(int i=1;i<=n;++i){
		read(ap),read(bp),read(as),read(bs);
		for(int j=0;j<=as;++j) f[i][j]=-1*j*ap;
		for(int j=0;j<=m;++j) f[i][j]=max(f[i][j],f[i-1][j]);
		if(i<=w) continue;
		l=1,r=0;
		for(int j=0;j<=m;++j){
			while(l<=r && q[l]<j-as) l++;// k>=j-as[i],此处是队头出队
			while(l<=r && f[i-w-1][q[r]]+q[r]*ap<=f[i-w-1][j]+j*ap) r--;// 保证是单调递减的
			q[++r]=j;
			if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*ap-j*ap);
		}
		l=1,r=0;
		for(int j=m;j>=0;--j){
			while(l<=r && q[l]>j+bs) l++;
			while(l<=r && f[i-w-1][q[r]]+q[r]*bp<=f[i-w-1][j]+j*bp) r--;
			q[++r]=j;
			if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*bp-j*bp);
		}
	}
	for(int i=0;i<=m;++i) ans=max(ans,f[n][i]);
	printf("%d\n",ans);
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:28:07  更:2021-10-16 19:30:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:02:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码