2021.9.25模拟赛

T1

题目描述

有无穷多个边长为1的正方形和边长为1的正三角形,问一共有多少种不同的方式,能够拼出一个边长为n的正十二边形。(要求使用的图形不能重叠,也不能存在空缺)
在这里插入图片描述
Subtask #1(20%):n≤4
Subtask #2(20%):n≤10
Subtask #3(20%):n≤103
Subtask #4(40%):无特殊限制
对于100%的数据,1≤n≤106。

Sol

通过手玩可以发现几个性质:
1. 150 ° = 90 ° + 60 ° 转 角 处 一 定 是 一 个 正 方 形 和 一 个 三 角 形 的 结 合 150°=90°+60° 转角处一定是一个正方形和一个三角形的结合 150°=90°+60°
2. 拐角的图形和边上的排列不一样
3. 一个图形最多排n-2层,因为摆到最后一层的时候是搞不到两个的
4. 对于每层的图形讨论,正方形和三角形最多用n次,当是0的时候就没法继续了
因此可以推出递推式:
f ( i , j ) = { 1 ! i ∣ ∣ ! j f ( i − 1 , j ) + f ( i , j − 1 ) f(i,j)= \begin{cases} 1& {!i||!j}\\ f(i-1,j)+f(i,j-1)& {} \end{cases} f(i,j)={1f(i1,j)+f(i,j1)!i!j

但是为 O ( n 2 ) O(n^2) O(n2),把这个写成组合数发现就是 f x , y = C x + y x f_{x,y}=C^x_{x+y} fx,y=Cx+yx,只需要求是 C 2 n n 2 \frac{C^n_{2n}}{2} 2C2nn

Code

#include<bits/stdc++.h>
#define I inline
#define RI register int 
#define int long long 
#define mod 998244353
using namespace std;

I int read()
{
	RI res=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch)){res=(res<<1)+(res<<3)+(ch&15);ch=getchar();}
	return res*f;
}
int x,y;
int n; int ans;
I int qpow(int ds,int zs){
	int ans=1;
	while(zs){
		if(zs&1)ans=(ans*ds)%mod;
		ds=(ds*ds)%mod;
		zs/=2;
	}
	return (ans+mod)%mod;
}
signed main()
{
	n=read();
	int c=1,c2=1;
	for(RI i=2*n;i>=n+1;i--)c=(c*i)%mod;
	for(RI i=1;i<=n;i++)c2=(c2*i)%mod;
	cout<<(c*qpow(c2,mod-2)%mod*qpow(2,mod-2)%mod);
	return 0;
}

T3

题目描述

在一个数轴上,假定 +1 为正方向,−1 为负方向,且 n 右边一个点为 1,1 左边一个点为 n。

现有一个会跳跃的动点,每次会向左/向右跳一步,当跳跃编号为 11 的倍数时,该动点会转变跳跃方向,当跳跃编号中含有数字 7 时,该动点也会转变跳跃方向。

特殊地,当跳跃编号既是 11 的倍数,也包含数字 7 时,只会转变一次跳跃方向。

初始时动点位于 1,且跳跃方向为 +1。

特殊地,该动点的第一次跳跃可以看作是原地跳了一下(位置和方向都不变)

由于这场比赛要水一点,所以 n=2333
现给出跳跃编号 k,求跳跃了 k 次后,动点所处的位置。

Sol

打表!!???

#include<bits/stdc++.h>
using namespace std;
int mod=2333,k;
bool pd(int x){if(x%11==0)  return 1; while(x)if(x%10==7)return 1;else x/=10;	return 0;}
int w,fs;
int wz[5000]={0,761,1586,1489,2250,2165,1090,1483,1483,1696,1278,2248,1487,662,759,2331,83,1158,
1158,1762,1975,1557,194,1766,941,1038,277,362,362,755,151,2271,356,1719,147,972,
875,1636,1636,378,2318,589,802,384,1354,593,2101,2198,2198,2283,1025,632,1236,1449,1031,2001,1240,415,415,1176,1091,16,409,2138,1925,10,1373,2134,2134,2231,1470
,1470,1470,1470,1470,1470,1470,1470,1470,1470,1470,709,794,1869,1476,2080,2293,1875,1875,303,1128,1031,1792,1707,632,1025,421,208,208,1178,417};
int fx[5000]={1,-1,1,-1,-1,1,-1,1,-1,1,-1,-1,1,-1,1,1,-1,-1,1,-1,1,-1,-1,1,-1,1,1,1,-1,-1,1,-1,1
,1,-1,1,-1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,1,-1,1,1,-1,1,-1,-1,1,1,-1,-1,1,-1,-1,1,-
1,1,1,1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,1,1,-1,1,1,1,-1,1,-1,-1,1,-1,-
1,1,1,-1,-1,1};
int main()
{
    cin>>k;
    w=wz[k/10000000];fs=fx[k/10000000];int n=k/10000000*10000000;
	for(int i=n+1;i<=k;i++){
		w+=fs;pd(i)? fs=-fs:0;if(w>mod)w=1;if(w<1)w=mod;

		}
		cout<<w;
	
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值