只能把补了的题目放这儿了,先留个坑,怕忘记。
Problem G URAL 1806 Mobile Telegraphs
题意是:给定n个电话号码,每个号码是一个长度为10的仅含'0'~'9'的字符串,每两个电话号码a,b之间能通信,需要满足一下条件之一:
1.b能通过改变a中某一个数字的值获得;
2.b能通过交换a中两个数字获得。
n个电话号码不相同,且相互通信的费用由之间的最长公共前缀长度决定。
分析:
对于一个电话号码逐位判断改变某一位的值得到哪些号码,或者交换某两个数字的得到哪些号码,由此判断该号码能与哪些号码通信,通信费用也可以很快求出。
然后就是dijkstra 或者spfa了。注意map存储LL判断的时候,前导0 可能会被忽略。
另外在spfa或dij里面进行边的转移,而不事先把边求出来可以加速过程。
1 #include <bits/stdc++.h> 2 #define esp 1e-6 3 #define inf 0x3f3f3f3f 4 #define pi acos(-1.0) 5 #define pb push_back 6 #define lson l, m, rt<<1 7 #define rson m+1, r, rt<<1|1 8 #define lowbit(x) (x&(-x)) 9 #define mp(a, b) make_pair((a), (b)) 10 #define bit(k) (1<<(k)) 11 #define iin freopen("pow.in", "r", stdin); 12 #define oout freopen("pow.out", "w", stdout); 13 #define in freopen("solve_in.txt", "r", stdin); 14 #define out freopen("solve_out.txt", "w", stdout); 15 #define bug puts("********))))))"); 16 #define Inout iin oout 17 #define inout in out 18 19 #define SET(a, v) memset(a, (v), sizeof(a)) 20 #define SORT(a) sort((a).begin(), (a).end()) 21 #define REV(a) reverse((a).begin(), (a).end()) 22 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 23 #define REP(i, n) for(int i = 0; i < (n); i++) 24 #define VREP(i, n, base) for(int i = (n); i >= (base); i--) 25 #define Rep(i, base, n) for(int i = (base); i < (n); i++) 26 #define REPS(s, i) for(int i = 0; (s)[i]; i++) 27 #define pf(x) ((x)*(x)) 28 #define mod(n) ((n)) 29 #define Log(a, b) (log((double)b)/log((double)a)) 30 #define Srand() srand((int)time(0)) 31 #define random(number) (rand()%number) 32 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 33 34 using namespace std; 35 typedef long long LL; 36 typedef unsigned long long ULL; 37 typedef vector<unsigned short> VI; 38 typedef pair<unsigned short,unsigned short> PII; 39 typedef vector<PII> VII; 40 typedef vector<PII, int> VIII; 41 typedef VI:: iterator IT; 42 typedef map<string, int> Mps; 43 typedef map<LL, int> Mpi; 44 typedef map<int, PII> Mpii; 45 typedef map<PII, int> Mpiii; 46 Mpi mps; 47 const int maxn = 20; 48 const int maxm = 50000 + 100; 49 50 unsigned short co[maxn]; 51 unsigned short pa[maxm]; 52 LL a[12]; 53 54 LL s[maxm]; 55 int n; 56 int d[maxm]; 57 bool inq[maxm]; 58 59 VII g[maxm]; 60 struct HeapNode 61 { 62 int d; 63 unsigned short u; 64 HeapNode() {} 65 HeapNode(int d, unsigned short u):d(d), u(u) {} 66 bool operator < (const HeapNode &rhs)const 67 { 68 return d > rhs.d; 69 } 70 }; 71 unsigned short cmp1(LL x, LL y) 72 { 73 char ss[2][12]; 74 sprintf(ss[0], "%010I64d", x); 75 sprintf(ss[1] ,"%010I64d", y); 76 int i = 0; 77 for(i = 0; i <= 9; i++) 78 { 79 if(ss[0][i] != ss[1][i]) 80 break; 81 } 82 return co[i]; 83 } 84 void bfs(int src) 85 { 86 priority_queue<HeapNode> q; 87 q.push(HeapNode(0, src)); 88 d[src] = 0; 89 inq[src] = false; 90 while(!q.empty()) 91 { 92 HeapNode u = q.top(); 93 int x = u.u; 94 int dd = u.d; 95 q.pop(); 96 if(inq[x]) 97 continue; 98 inq[x] = true; 99 char ss[12]; 100 sprintf(ss+1, "%010I64d", s[x]); 101 Rep(j, 1, 11) 102 { 103 int c = ss[11-j]-'0'; 104 REP(k, 10) 105 { 106 if(k == c) 107 continue; 108 LL tmp = s[x] + (k-c)*a[j-1]; 109 if(mps.count(tmp)) 110 { 111 int y = mps[tmp]; 112 int l = cmp1(s[x], s[y]); 113 if(d[y] > dd + l) 114 { 115 pa[y] = x; 116 d[y] = dd + l; 117 q.push(HeapNode(d[y], y)); 118 } 119 } 120 } 121 } 122 Rep(j, 1, 11) for(int k = j+1; k <= 10; k++) 123 { 124 int c1 = ss[11-j]-'0'; 125 int c2 = ss[11-k]-'0'; 126 if(c1 == c2) 127 continue; 128 LL tmp = s[x] + (c2-c1)*a[j-1] + (c1-c2)*a[k-1]; 129 if(mps.count(tmp)) 130 { 131 int y = mps[tmp]; 132 int l = cmp1(s[x], s[y]); 133 if(d[y] >dd + l) 134 { 135 pa[y] = x; 136 d[y] = dd + l; 137 q.push(HeapNode(d[y], y)); 138 } 139 } 140 } 141 } 142 } 143 VI ans; 144 145 void print(int s) 146 { 147 ans.pb(s); 148 while(1) 149 { 150 s = pa[s]; 151 ans.pb(s); 152 if(s == 1) 153 break; 154 } 155 printf("%d\n", ans.size()); 156 VREP(i, ans.size()-1, 0) 157 { 158 printf("%hu%c", ans[i], i == 0 ? '\n' : ' '); 159 } 160 } 161 int main() 162 { 163 164 a[0] = 1; 165 Rep(i, 1, 11) 166 a[i] = a[i-1]*10; 167 scanf("%d", &n); 168 REP(i, 10) 169 scanf("%hu", co+i); 170 Rep(i, 1, n+1) 171 { 172 scanf("%I64d", s+i); 173 mps[s[i]] = i; 174 d[i] = inf; 175 inq[i] = false; 176 } 177 178 bfs(1); 179 if(d[n] >= inf) 180 puts("-1"); 181 else 182 { 183 printf("%d\n", d[n]); 184 print(n); 185 } 186 return 0; 187 }
Problem D URAL 1803 The Czechs' Rifles
题意:实际上就是要你求出前n个斐波那契数的k进制表示下,各个位数之和,然后再排序输出。
分析:首先可以证明的是,fn <= 2*fn-1,所以fn <= 2^n,所以可以这样求每个斐波那契数的k进制表示下各数位之和,将其表示成cnt进制的数,cnt为不超过n的k的最大次幂,
然后预处理出来小于cnt的各个数的k进制下数位之和。接下来就是通过前两项酸算出当前的斐波那契数,然后并将其k进制下各位加起来。这个过程其实就是模拟的一个大数加法的过程。
1 #include <bits/stdc++.h> 2 #define in freopen("solve_in.txt", "r", stdin); 3 using namespace std; 4 const int maxn = 50000 + 100; 5 struct Node 6 { 7 int id, su; 8 bool operator < (const Node &rhs)const 9 { 10 if(su == rhs.su) 11 return id < rhs.id; 12 return su < rhs.su; 13 } 14 } ans[maxn]; 15 int sum[maxn]; 16 int dp[2][maxn]; 17 18 int n, k; 19 int main() 20 { 21 22 scanf("%d%d", &k, &n); 23 int cnt = 1; 24 while(cnt * k < maxn) 25 cnt *= k; 26 for(int i = 0; i < maxn; i++) 27 { 28 int tmp = i; 29 while(tmp) 30 { 31 sum[i] += tmp%k; 32 tmp /= k; 33 } 34 } 35 dp[0][0] = dp[1][0] = 1; 36 ans[1].id = 1, ans[2].id = 2; 37 ans[1].su = ans[2].su = 1; 38 int st = 1; 39 for(int i = 3; i <= n; i++) 40 { 41 int delta = 0; 42 int now = i&1; 43 int pre = now^1; 44 ans[i].id = i; 45 for(int k = 0; k < st; k++) 46 { 47 dp[now][k] += dp[pre][k] + delta; 48 if(dp[now][k] >= cnt) 49 { 50 delta = dp[now][k]/cnt; 51 dp[now][k] %= cnt; 52 } 53 else delta = 0; 54 ans[i].su += sum[dp[now][k]]; 55 } 56 if(delta) 57 dp[now][st++] = delta; 58 ans[i].su += sum[delta]; 59 } 60 std::sort(ans+1, ans+1+n); 61 for(int i = 1; i <= n; i++) 62 printf("%d%c", ans[i].id, i == n ? '\n' : ' '); 63 return 0; 64 }