扩展欧拉降幂,维护不同模phi下的ans,观察可得后面一堆phi是2的倍数,当指数很大时取模都是1,所以只要维护8层phi就好了
⼀一个显然的结论:每个位置最多被两个区间覆盖
•所有区间按照右端点从小到大排序
•dp(i, j)表示第i个区间必选,上⼀一次被覆盖⼀一次的位置是j,[1, j]覆盖权值和最⼤大值 的最小值
•dp(i, j) = min(max(dp(k, l), w(i) + w(k)) R(k) +1 >= L(i) and L(k) -1 <= l < L(i) •j和R(k)有关
#include <cstdio> #include <cstdlib> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <vector> #include <string> #include <map> using namespace std; struct node { int le,ri,wi; }; node seg[2010]; int n,m; int dp[2010][2010]; void init() { memset(dp,0x3f,sizeof(dp)); } bool cmp(const node &a,const node &b) { if(a.ri==b.ri) return a.wi<b.wi; return a.ri<b.ri; } int main() { int i,j; int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d%d%d",&seg[i].le,&seg[i].ri,&seg[i].wi); } init(); sort(seg+1,seg+1+n,cmp); int ans=dp[0][0]; for(i=1;i<=n;i++) { if(seg[i].le==1) dp[i][0]=seg[i].wi; for(j=1;j<=i;j++) { if(seg[j].ri<seg[i].le-1) continue; int maxx=dp[j][seg[i].le-1]; if (seg[j].ri>=seg[i].le) maxx=max(maxx,seg[i].wi+seg[j].wi); else maxx=max(maxx,max(seg[i].wi,seg[j].wi)); dp[i][seg[j].ri]=min(dp[i][seg[j].ri],maxx); } for(j=seg[i].le;j<=seg[i].ri;j++) { dp[i][j]=min(dp[i][j],dp[i][j-1]); } if(seg[i].ri==m) ans=min(ans,dp[i][m]); } if(ans==0x3f3f3f3f) ans=-1; printf("%d\n",ans); } return 0; }
这题主要是结论难得找,找到结论后就是一个数位DP板题了
#include <cstdio> #include <cstdlib> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <vector> #include <string> #include <map> using namespace std; const long long mod=1e9+7; long long n; long long dp[70][150][4]; int num[70],len; //pre表示上一个填的啥,pre=0表示还没填任何数(没出现第一个1). //state表示相邻对有多少相同和不同,因为可能为负,所以加上偏移量66 long long dfs(int pos,int state,int lim,int pre) { // cout<<pos<<" "<<state<<endl; if(pos==-1) return abs(state-66); if(!lim&&dp[pos][state][pre]!=-1) return dp[pos][state][pre]; int up=lim?num[pos]:1; long long cnt=0; for(int i=0;i<=up;i++) { if(pre==2) { if(i==1) cnt+=dfs(pos-1,state,lim&&i==up,i); else cnt+=dfs(pos-1,state,lim&&i==up,pre); } else cnt+=dfs(pos-1,state+(i==pre?1:-1),lim&&i==up,i); } cnt%=mod; if(!lim) dp[pos][state][pre]=cnt; return cnt; } long long solve(long long a) { len=0; while(a>0) { num[len++]=a%2; a/=2; } return dfs(len-1,66,1,2); } int main() { int T; memset(dp,-1,sizeof(dp)); scanf("%d",&T); while(T--) { scanf("%lld",&n); printf("%lld\n",solve(n)); } return 0; }