Age of Moyu:
这个题只要看到隐藏的一个线索就可以做了。
因为这里的权值都是1,如果当前有一种方案最短路大于原先的,但是可以增加一种新颜色,这样也不需要加入,因为我们到了u点后,到后面都是需要变成他的后继边里的某一边且只需要花费1的代价。
所以对于大于的方案就可以省去。
但是可能存在多个最短路距离一样颜色不用的情况,所以我们可以用set记录每个点最短距离包含的颜色数,来更行。
这里用spfa来更快,因为标记一下,如果在队列里没更新到,那么因为我们已经插入到set里了,就不需要再放入队列了。
这题还有好多玄学问题。。两个初始化位置从1开始就超时,一定要从0开始。而且快读被卡掉了。。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,set<int>> pii; const int N = 1e5 + 5; const int M = 1e5 + 5; const LL Mod = 199999; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; int n,m; typedef pair<int,int> pt; struct Node{int to,col;}; vector<Node> G[N]; pii dis[N]; bool vis[N]; void solve() { queue<int> Q; for(int i = 0;i <= n;++i) dis[i].first = INF,dis[i].second.clear(); dis[1].first = 0; Q.push(1); while(!Q.empty()) { int u = Q.front(); Q.pop(); vis[u] = 0; for(auto v : G[u]) { int cost = (dis[u].second.find(v.col) == dis[u].second.end()); if(dis[v.to].first > dis[u].first + cost) { dis[v.to].first = dis[u].first + cost; dis[v.to].second.clear(); dis[v.to].second.insert(v.col); if(vis[v.to] == 0) { vis[v.to] = 1; Q.push(v.to); } } else if(dis[v.to].first == dis[u].first + cost && (dis[v.to].second.find(v.col) == dis[v.to].second.end())) { dis[v.to].second.insert(v.col); if(vis[v.to] == 0) { vis[v.to] = 1; Q.push(v.to); } } } } } int main() { while(~scanf("%d %d",&n,&m)) { for(int i = 0;i <= n;++i) G[i].clear(); while(m--) { int x,y,z;scanf("%d %d %d",&x,&y,&z); G[x].push_back(Node{y,z}); G[y].push_back(Node{x,z}); } solve(); printf("%d\n",dis[n].first == INF ? -1 : dis[n].first); } // system("pause"); return 0; }View Code
Sequence:
这题真的想到了做法,但是一开始觉得不太可能这样做。(为什么不相信自己,去尝试一下呢。。
首先这里很明显是矩阵快速幂,但是这个向下取整的东西不好搞。
但是又可以想到,我们可以整除分块去求他。
然后就在整除分块里跑矩阵快速幂就行了。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,set<int>> pii; const int N = 1e6 + 5; const int M = 1e5 + 5; const LL Mod = 1e9 + 7; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline int read(){ int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; LL ADD(LL a,LL b) {return (a + b) % Mod;} struct Mat{ LL m[5][5]; Mat operator * (Mat &a)const{ Mat c;memset(c.m,0,sizeof(c.m)); for(int i = 1;i <= 3;++i) { for(int j = 1;j <= 3;++j) { for(int k = 1;k <= 3;++k) { c.m[i][j] = ADD(c.m[i][j],m[i][k] * a.m[k][j] % Mod); } } } return c; } }; Mat quick_mi(Mat a,LL b) { Mat res;memset(res.m,0,sizeof(res.m)); for(int i = 1;i <= 3;++i) res.m[i][i] = 1; while(b) { if(b & 1) res = res * a; a = a * a; b >>= 1; } return res; } LL f[5]; int main() { int ca;ca = read(); while(ca--) { int A,B,C,D,P,n; A = read() % Mod,B = read() % Mod,C = read() % Mod,D = read() % Mod,P = read(),n = read(); f[1] = A,f[2] = B; if(n == 1) printf("%lld\n",f[1]); else if(n == 2) printf("%lld\n",f[2]); else { LL tmp; for(int L = 3,r = 0;L <= n;L = r + 1) { if(P / L == 0) r = n; else r = min(n,P / (P / L)); // printf("L is %d r is %d\n",L,r); int len = r - L + 1; LL k = P / L; Mat ans;memset(ans.m,0,sizeof(ans.m)); if(len == 1) { f[3] = D * f[2] % Mod + C * f[1] % Mod + k; f[3] %= Mod; f[1] = f[2]; f[2] = f[3]; tmp = f[3]; } else if(len == 2) { f[3] = D * f[2] % Mod + C * f[1] % Mod + k; f[3] %= Mod; f[4] = D * f[3] % Mod + C * f[2] % Mod + k; f[4] %= Mod; f[2] = f[4],f[1] = f[3]; tmp = f[4]; } else { // printf("L is %d r is %d f[2] is %lld f[1] is %lld\n",L,r,f[2],f[1]); f[3] = D * f[2] % Mod + C * f[1] % Mod + k; f[3] %= Mod; f[4] = D * f[3] % Mod + C * f[2] % Mod + k; f[4] %= Mod; Mat a;memset(a.m,0,sizeof(a.m)); a.m[1][1] = D,a.m[1][2] = C,a.m[1][3] = 1; a.m[2][1] = 1,a.m[3][3] = 1; ans.m[1][1] = f[4],ans.m[2][1] = f[3],ans.m[3][1] = k; a = quick_mi(a,len - 2); ans = a * ans; f[2] = ans.m[1][1],f[1] = ans.m[2][1]; tmp = f[2]; // printf("f[2] is %lld f[1] is %lld\n",f[2],f[1]); } } printf("%lld\n",tmp); } } system("pause"); return 0; } /* 2 1 2 3 4 10 10 */View Code