接着昨晚一个没AC的题 Recursive sequence 矩阵快速幂&递推
给我们递推公式 F(n)=F(n-1)+F(n-2)*2+n4 求第n项 对mod=2147493647余
其实就是一个水题吧,因为之前我用过矩阵快速幂求FIB(n)%mod的板子
但是不知道具体原理 QAQ 线代上学期考了不多不少刚好60
矩阵学习&矩阵快速幂 贴一手(sdl
简单的说 设矩阵A F (如果单纯的求Ak 就不细讲了)
存在递推关系式 F(n)=pF(n-1)+qF(n-2)
设置初始矩阵 【F(n) F(n-1) F(n-2)】 (线代太弱了,我还是习惯于这样子存) 1M的矩阵 需要构造一个M1的矩阵 做矩阵乘法得到 【F(n+1) F(n) F(n-1)】 那么显然每乘一次递推矩阵A 就可以得到下一个状态
-
- 就是构造递推矩阵有点麻烦 其他的 基本上很好理解
- – ------ 应该还是很好理解吧 就是自己推一下初始矩阵 以及递推矩阵
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
inline ll read(){char c=getchar();ll f=1,x=0;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}return x*f;}
const int mod = 2147493647;
int aa,bb,n;
struct Matrix {
int a[9][9];
Matrix() { memset(a, 0, sizeof a); }
Matrix operator*(const Matrix &b) const {
Matrix res;
for (int i = 1; i <= 8; ++i)
for (int j = 1; j <= 8; ++j)
for (int k = 1; k <= 8; ++k)
res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return res;
}
} ans, base;
void init() {
base.a[1][1]=1;
base.a[1][2]=1;
base.a[1][3]=0;
base.a[1][4]=0;
base.a[1][5]=0;
base.a[1][6]=0;
base.a[1][7]=0;
base.a[1][8]=0;
base.a[2][1]=2;
base.a[2][2]=0;
base.a[2][3]=1;
base.a[2][4]=0;
base.a[2][5]=0;
base.a[2][6]=0;
base.a[2][7]=0;
base.a[2][8]=0;
base.a[3][1]=0;
base.a[3][2]=0;
base.a[3][3]=0;
base.a[3][4]=0;
base.a[3][5]=0;
base.a[3][6]=0;
base.a[3][7]=0;
base.a[3][8]=0;
base.a[4][1]=1;
base.a[4][2]=0;
base.a[4][3]=0;
base.a[4][4]=1;
base.a[4][5]=0;
base.a[4][6]=0;
base.a[4][7]=0;
base.a[4][8]=0;
base.a[5][1]=4;
base.a[5][2]=0;
base.a[5][3]=0;
base.a[5][4]=4;
base.a[5][5]=1;
base.a[5][6]=0;
base.a[5][7]=0;
base.a[5][8]=0;
base.a[6][1]=6;
base.a[6][2]=0;
base.a[6][3]=0;
base.a[6][4]=6;
base.a[6][5]=3;
base.a[6][6]=1;
base.a[6][7]=0;
base.a[6][8]=0;
base.a[7][1]=4;
base.a[7][2]=0;
base.a[7][3]=0;
base.a[7][4]=4;
base.a[7][5]=3;
base.a[7][6]=2;
base.a[7][7]=1;
base.a[7][8]=0;
base.a[8][1]=1;
base.a[8][2]=0;
base.a[8][3]=0;
base.a[8][4]=1;
base.a[8][5]=1;
base.a[8][6]=1;
base.a[8][7]=1;
base.a[8][8]=1;
ans.a[1][2] =bb;
ans.a[1][3] =aa; //初始值
ans.a[1][1] =aa*2+bb+81;
ans.a[1][4]=81;
ans.a[1][5]=27;
ans.a[1][6]=9;
ans.a[1][7]=3;
ans.a[1][8]=1;
}
/*
[p 1
q 0]*/
void qpow(int b) {
while (b) {
if (b & 1) ans = ans * base;
base = base * base;
b >>= 1;
}
}
signed main() {
ll t=read();
while(t--){
n=read();
aa=read();
bb=read();
if(n==1){
printf("%lld\n",aa%mod);
continue;
}
if(n==2){
printf("%lld\n",bb%mod);
continue;
}
init();
qpow(n-3);
printf("%lld\n",ans.a[1][1]%mod);
}
return 0;
}
理解了原理后感觉也蛮简单的(或许是错觉) 贴一个模板题
数列加速 洛谷
不是很明显的递推关系式&矩阵加速
给你p=a+b q=a*b 求 (an +bn ) %264
QAQ原来模264 让它自然溢出就好了 (长见识了
我们的目的是递推F(n)= (an +bn ) 那么就尝试拿F(n-1) F(n-2) 去凑吧 (我凑了一会
递推关系式找到了以后 写一下初始矩阵以及递推矩阵就好了
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll unsigned long long
#define int unsigned long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
inline ll read(){char c=getchar();ll f=1,x=0;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}return x*f;}
ll aa,bb,n,p,q,mod=1;
struct Matrix {
int a[9][9];
Matrix() { memset(a, 0, sizeof a); }
Matrix operator*(const Matrix &b) const {
Matrix res;
for (int i = 1; i <= 3; ++i)
for (int j = 1; j <= 3; ++j)
for (int k = 1; k <= 3; ++k)
res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]);
return res;
}
} ans, base;
void init() {
base.a[1][1]=p;
base.a[1][2]=1;
base.a[1][3]=0;
base.a[2][1]=-q;
base.a[2][2]=0;
base.a[2][3]=1;
base.a[3][1]=0;
base.a[3][2]=0;
base.a[3][3]=0;
ans.a[1][2] =p*p-2*q;
ans.a[1][3] =p; //初始值
ans.a[1][1] =p*ans.a[1][2]-q*ans.a[1][3];
}
/*
[p 1
q 0]*/
void qpow(int b) {
while (b) {
if (b & 1) ans = ans * base;
base = base * base;
b >>= 1;
}
}
signed main() {
ll t=read();
ll add=0;
while(t--){
p=read();
q=read();
n=read();
add++;
printf("Case %lld: ",add);
if(n==0){
printf("2\n");
continue;
}
if(n==1){
printf("%llu\n",p);
continue;
}
if(n==2){
printf("%llu\n",(p*p-2*q));
continue;
}
init();
qpow(n-3);
printf("%llu\n",ans.a[1][1]);
}
return 0;
}
(矩阵加速真心快
2013年长沙邀请赛 &矩阵快速幂
我tm傻逼了 和上文一样,一直都是以【F(n),F(n-1),F(n-2)】去递推
然后这个题发现推第三项很困难 - - 发呆一小时
既然F(n)可以由F(n-1) F(n-2) 推过来 那么直接在递推矩阵里面实现不就好了 - - 傻逼了傻逼了
假设C(n)=(a+sqrt(b) )n + (a-sqrt(b) )n
(a-1)2 <b<a2 那么对于【S1=a+sqrt(b)】 可以知道a>sqrt(b)>a-1
那么显然 S1=2*a 也就是说 【C(n)】=S(n)
接下来就是推C(n)了 - - – 很简单自己推一下吧
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
inline ll read(){char c=getchar();ll f=1,x=0;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}return x*f;}
int aa,bb,n,mod;
struct Matrix {
int a[9][9];
Matrix() { memset(a, 0, sizeof a); }
Matrix operator*(const Matrix &b) const {
Matrix res;
for (int i = 1; i <= 2; ++i)
for (int j = 1; j <= 2; ++j)
for (int k = 1; k <= 2; ++k)
res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return res;
}
} ans, base;
void init() {
base.a[1][1]=0;
base.a[1][2]=((bb-aa*aa)%mod+mod)%mod;
base.a[2][1]=1;
base.a[2][2]=2*aa;
ans.a[1][2] =(int)ceil((aa*aa%mod+bb)%mod+2*aa*sqrt(bb))%mod ;
ans.a[1][1] =2*aa%mod;
}
/*
[p 1
q 0]*/
void qpow(int b) {
while (b) {
if (b & 1) ans = ans * base;
base = base * base;
b >>= 1;
}
}
signed main() {
while(scanf("%lld%lld%lld%lld",&aa,&bb,&n,&mod)!=EOF){
init();
qpow(n-1);
printf("%lld\n",ans.a[1][1]%mod);
}
return 0;
}
-
- 罢了矩阵快速幂就先练到这里
思维水题&数论不配
晚饭后A一题 大概意思就是一个很大的画板起初全是白色的 然后你有a次红色填涂的鸡会和b次蓝色颜色的填涂鸡会,最终形成的图形要满足
首先是个矩阵包含了a+b块颜色的格子 然后至少有一种颜色的格子能够形成矩形 问我们构造出来的这种矩形的最小周长是多少
刚开始我想当的是纯粹是个给你a+b 也就是总面积s=a+b 的 矩形 求它的最小面积 然后交了一发WA37 好叭我承认没读懂题QAQ
实际上要这样子枚举它 枚举边i =1开始 i*i<=s 然后因为我们要至少使得红色或者蓝色的块是矩形 要满足a%i=0 或者b%i =0 所以满足这个条件的i 边长 才能考虑拿去做整体矩形的边长 然后我们判断n%i=0 满足就进行整体周长的最小值维护 就OK了
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
ll qp(ll a,ll b,ll mod){ll ans=1;if(b==0){return ans%mod;}while(b){if(b%2==1){b--;ans=ans*a%mod;}a=a*a%mod;b=b/2;}return ans%mod;}//快速幂%
ll qpn(ll a,ll b, ll p){ll ans = 1;a%=p;while(b){if(b&1){ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元 (分子*qp(分母,mod-2,mod))%mod;
ll fact_pow(ll n,ll p){ll res=0;while(n){n/=p;res+=n;}return res;}
ll mult(ll a,ll b,ll p)
{
a%=p;
b%=p;
ll r=0,v=a;
while(b)
{
if(b&1)
{
r=(r+v)%p;
r=(r+p)%p;
}
v<<=1;
v=(v+p)%p;
b>>=1;
}
return r%p;
}
ll pow_mod(ll x,ll n,ll mod)
{
ll res=1;
while(n)
{
if(n&1)
res=mult(res,x,mod);
x=mult(x,x,mod);
n>>=1;
}
return res;
}
ll quick_pow(ll a,ll b,ll p){ll r=1,v=a%p;while(b){if(b&1)r=mult(r,v,p);v=mult(v,v,p);b>>=1;}return r;}
bool CH(ll a,ll n,ll x,ll t)
{ll r=quick_pow(a,x,n);ll z=r;for(ll i=1;i<=t;i++){r=mult(r,r,n);if(r==1&&z!=1&&z!=n-1)return true;z=r;}return r!=1;}
bool Miller_Rabin(ll n)
{if(n<2)return false;if(n==2)return true;if(!(n&1))return false;ll x=n-1,t=0;while(!(x&1)){x>>=1;t++;}
srand(time(NULL));ll o=8;for(ll i=0;i<o;i++){ll a=rand()%(n-1)+1;if(CH(a,n,x,t))return false;}return true;}
ll exgcd(ll a,ll b,ll &x,ll &y){
if (!b){
x=1,y=0;
return a;
}
ll ans=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return ans;
}
ll INV(ll a,ll b){ll x,y;return exgcd(a,b,x,y),(x%b+b)%b;}
ll crt(ll x,ll p,ll mod){return INV(p/mod,mod)*(p/mod)*x;}
ll FAC(ll x,ll a,ll b)
{if(!x)return 1;ll ans=1;for(ll i=1;i<=b;i++)if(i%a)ans*=i,ans%=b;
ans=pow_mod(ans,x/b,b);for(ll i=1;i<=x%b;i++)if(i%a)ans*=i,ans%=b;return ans*FAC(x/a,a,b)%b;}
ll C(ll n,ll m,ll a,ll b)
{ll N=FAC(n,a,b),M=FAC(m,a,b),Z=FAC(n-m,a,b),sum=0,i;for(i=n;i;i=i/a)sum+=i/a;
for(i=m;i;i=i/a)sum-=i/a;for(i=n-m;i;i=i/a)sum-=i/a;return N*pow_mod(a,sum,b)%b*INV(M,b)%b*INV(Z,b)%b;}
ll exlucas(ll n,ll m,ll p)
{ll t=p,ans=0,i;for(i=2;i*i<=p;i++){ll k=1;while(t%i==0){k*=i,t/=i;}
ans+=crt(C(n,m,i,k),p,k),ans%=p;}if(t>1)ans+=crt(C(n,m,t,t),p,t),ans%=p;return ans % p;}
ll H(ll x,ll p) //错排
{
ll ans=0;
if(x==0)return 1;
x=x%(2*p);
if(x==0)x=2*p;
for(int i=2;i<=x;++i)
ans=(ans*i+(i%2==0?1:-1))%p;
return (ans+p)%p;
}
set<ll>seet;
int main(){
ll add=1e17;
ll a,b,s;
read(a);
read(b);
ll op=gcd(a,b);
ll rnm=min(a,b);
//read(s);
s=a+b;
for(ll i=1;i*i<=s;i++){
if(a%i==0){
seet.insert(a/i);
}
if(b%i==0){
seet.insert(b/i);
}
if(s%i==0){
if(*seet.begin()<=s/i){
add=min(add,i*2+s/i*2);
}
}
}
printf("%lld\n",add);
return 0;
}
正解没暴力好理解的exgcd题
给我们n p w d 和xw+yd=p这个式子 exgcd能提供一组解但是不一定符合题意 根据线代的知识 通解啥的带进去枚举搞就好了
int main(){
ll n=read(),p=read(),w=read(),d=read();
for(int y=0;y<w;y++){
if((p-d*y)%w){
continue;}
ll x=(p-d*y)/w;
if(y+x<=n&&x>=0){
cout<<x<<" "<<y<<" "<<n-y-x;
return 0;
}
else break;
}
cout<<"-1";
return 0;
}
害,看了眼数据结构专题好像没一个会写的 (大佬们7 8题起步 ORZ
现场学一手单调队列维护 签到
太菜了 明天开始数据结构 操了
#include<bits/stdc++.h>
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
inline ll read(){char c=getchar();ll f=1,x=0;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}return x*f;}
const int mod =1e7+7;
int aa,bb,n,m;
struct Matrix {
int a[25][25];
Matrix() { memset(a, 0, sizeof a); }
Matrix operator*(const Matrix &b) const {
Matrix res;
for (int i = 1; i <=n+2; ++i)
for (int j = 1; j <=n+2; ++j)
for (int k = 1; k <=n+2; ++k)
res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return res;
}
} ans, base;
void init() {
memset(ans.a,0,sizeof(ans.a));
memset(base.a,0,sizeof(base.a));
ans.a[1][1]=23;
for(int i=2;i<=n+1;i++){
ans.a[1][i]=read();
}
ans.a[1][n+2]=3; //n+2 行初始矩阵
for(int i=1;i<=n+1;i++){
base.a[1][i]=10;
base.a[n+2][i]=1;
}
base.a[1][n+2]=0;
base.a[n+2][n+2]=1;
for(int i=2;i<=n+1;i++){
for(int j=1;j<=n+1;j++){
if(j>=i){
base.a[i][j]=1;}
else{
base.a[i][j]=0;
}
}
}
}
/*
[p 1
q 0]*/
void qpow(int b) {
while (b) {
if (b & 1) ans = ans * base;
base = base * base;
b >>= 1;
}
}
signed main() {
while(scanf("%lld%lld",&n,&m)!=EOF){
init();
qpow(m);
printf("%lld\n",ans.a[1][n+1]%mod);
}
return 0;
}