洛谷 5135 painting
分析
可以发现对于 o p t = 1 opt=1 opt=1时,答案为 C ( n , m ) C(n,m) C(n,m),对于 o p t = 0 opt=0 opt=0时,可以认为是不降序列,那么使它变成递增序列,取值变成了 [ 1 ∼ n + m ] [1\sim n+m] [1∼n+m],答案为 C ( n + m − 1 , m ) C(n+m-1,m) C(n+m−1,m),所以就是这样的,这是我比赛唯一切掉的QaQ
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long ll;
const ll mod=1000000007ll;
const int N=1000000; ll inv[N];
inline ll iut(){
rr ll ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
inline ll ksm(ll x,ll y){
rr ll ans=1;
for (;y;y>>=1,(x*=x)%=mod)
if (y&1) (ans*=x)%=mod;
return ans;
}
inline void print(ll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed main(){
rr ll tt=1;
for (rr int i=1;i<=N;++i) (tt*=i)%=mod;
inv[N]=ksm(tt,mod-2); inv[1]=1;
for (rr int i=N;i>1;--i) inv[i-1]=inv[i]*i%mod;
for (rr int t=iut();t;--t){
rr ll a=iut(),b=iut(),ans=inv[b];
(a+=(1-iut())*(b-1))%=mod;
for (rr ll i=a;i>a-b;--i) (ans*=i)%=mod;
print(ans); putchar(10);
}
return 0;
}
洛谷 5136 sequence
分析
根据oeis,可以得到 a ( n ) = 3 ∗ F i b o n a c c i ( n − 1 ) + F i b o n a c c i ( n − 2 ) + ( n m o d 2 ) , n > 0 a(n)=3∗Fibonacci(n−1)+Fibonacci(n−2)+(n\bmod2),n>0 a(n)=3∗Fibonacci(n−1)+Fibonacci(n−2)+(nmod2),n>0,所以矩阵乘法来一波
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int mod=998244353;
struct maix{int p[2][2];}A,ANS;
inline long long iut(){
rr long long ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline maix mul(maix A,maix B,int k){
rr maix C;
for (rr int i=0;i<k;++i)
for (rr int j=0;j<2;++j) C.p[i][j]=0;
for (rr int i=0;i<k;++i)
for (rr int j=0;j<2;++j)
for (rr int k=0;k<2;++k)
C.p[i][j]=(1ll*A.p[i][k]*B.p[k][j]+C.p[i][j])%mod;
return C;
}
signed main(){
for (rr int t=iut();t;--t){
rr long long n=iut()-1; rr int k=(n&1)^1; n=n%1996488708;
if (!n) {printf("1\n"); continue;}
A.p[0][0]=1; A.p[0][1]=1; A.p[1][0]=1; A.p[1][1]=0;
ANS.p[0][0]=1; ANS.p[0][1]=0; ANS.p[1][0]=0; ANS.p[1][1]=0;
for (;n;n>>=1,A=mul(A,A,2))
if (n&1) ANS=mul(ANS,A,1);
printf("%d\n",(ANS.p[0][0]+(ANS.p[0][1]<<1)%998244353+k)%998244353);
}
return 0;
}
洛谷 5137 polynomial
分析
万恶的出题人卡掉了逆元,虽然我那时什么都不会,可以像出题人那样利用分治
注意乘法爆long long
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long ll;
ll a1,b1,n,a,b,mod;
inline ll iut(){
rr ll ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline ll mo(ll a,ll b){return a+b>=mod?a+b-mod:a+b;}
inline ll mo2(ll a,ll b){return a<b?a-b+mod:a-b;}
inline ll mul(ll a,ll b){
a%=mod,b%=mod;
rr ll t=(long double)a*b/mod,ans=a*b-t*mod;
if (ans<0) ans+=mod;
else if (ans>=mod) ans-=mod;
return ans;
}
inline ll dfs(ll n){
if (n<=1) return !n?1:mo(a,b);
rr ll ans=dfs(n>>1);
a1=mul(a1,a1),b1=mul(b1,b1);
if ((n>>1)&1) a1=mul(a1,a),b1=mul(b1,b);
return n&1?mul(mul(a1,a)+mul(b1,b),ans):mo2(mul(a1+b1,ans),mul(a1,b1));
}
signed main(){
for (rr int t=iut();t;--t){
n=iut(),a=iut(),b=iut(),mod=iut(),a1=b1=1;
printf("%lld\n",dfs(n));
}
return 0;
}
后续
原谅我当时只会排列组合