题目
比赛
题意:
一个无向图,从起点出发,T时间内要到达终点。所有点都有一个景观值,可以游览,但是游览需要额外的时间,而且游览的景点的游览值必须比前一次要大。求最大的游览值和。
题解:
按游览值排序,用一个dp[i][j]数组表示j时间游览了i的最大游览值和。只能从前面的游览值比i小的转移。注意是从起点出发的,最后要到终点(游览终点的话时间也要算在T内)。
//Time:156ms //Memory:360KB //Length:1520B #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #define MAXN 110 #define FI first #define SE second using namespace std; long long toz(long long n,long long mod) { if(n>0) return n%mod; else return mod-(-n)%mod; } void mul(long long a[2][2],long long b[2][2],long long mod) { long long tmp[2][2]={{0}}; for(int i=0;i<2;++i) for(int j=0;j<2;++j) for(int k=0;k<2;++k) tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod; for(int i=0;i<2;++i) for(int j=0;j<2;++j) a[i][j]=tmp[i][j]; } void pow_mod(long long a[2][2],long long p,long long mod) { long long ans[2][2]={{0}}; ans[0][0]=ans[1][1]=1; while(p) { if(p&1) mul(ans,a,mod); mul(a,a,mod); p>>=1; } for(int i=0;i<2;++i) for(int j=0;j<2;++j) a[i][j]=ans[i][j]; } int main() { //freopen("/home/moor/Code/input.txt","r",stdin); long long a,b,n,m,c,a1,a2; while(cin>>a>>b>>n>>m) { long long num[2][2]; c=toz(-a*a+b,m); num[0][0]=2*a%m,num[0][1]=1; num[1][0]=c,num[1][1]=0; a1=(long long )ceil(a+sqrt(b*1.0))%m; a2=(2*a*a+2*b)%m; if(n>=3) { pow_mod(num,n-2,m); long long tmp[2][2]={{0}}; tmp[0][0]=a2,tmp[0][1]=a1; mul(tmp,num,m); cout<<tmp[0][0]<<'\n'; } else cout<<(n==1?a1:a2)<<'\n'; } return 0; }