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(i−1,j)+f(i,j−1)!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;
}