Codeforces_793
A.找最小的数,看每个数跟它的差是否被k整除。
#include<bits/stdc++.h> #define MOD 1000000007 using namespace std; int n,cnt[100005] = {0},ans[100005],two[100005]; int main() { ios::sync_with_stdio(false); cin >> n; while(n--) { int x; cin >> x; for(int i = 1;i*i <= x;i++) { if(x%i == 0) { cnt[i]++; if(i*i != x) cnt[x/i]++; } } } two[0] = 1; for(int i = 1;i <= 100000;i++) two[i] = two[i-1]*2%MOD; for(int i = 1;i <= 100000;i++) ans[i] = two[cnt[i]]-1; for(int i = 100000;i >= 1;i--) { for(int j = i*2;j <= 100000;j += i) ans[i] = (ans[i]-ans[j]+MOD)%MOD; } cout << ans[1] << endl; return 0; }
B.直接dfs记录方向和转弯次数,不做其他剪枝就能过。
#include<bits/stdc++.h> #define MOD 1000000007 using namespace std; int n,m,vis[1005][1005][2] = {0},x1,Y1,flag = 0; int dx[4] = {-1,0,1,0}; int dy[4] = {0,-1,0,1}; string a[1005]; void dfs(int x,int y,int d,int cnt) { if(cnt > 2) return; if(flag) return; if(a[x][y] == 'T') flag = 1; if(d != -1) vis[x][y][d] = 1; for(int i = 0;i < 4;i++) { if((i+2)%4 == d) continue; int xx = x+dx[i],yy = y+dy[i]; if(xx < 1 || xx > n || yy < 1 || yy > m || a[xx][yy] == '*') continue; if(vis[xx][yy][i]) continue; dfs(xx,yy,i,cnt+(i != d)); } } int main() { ios::sync_with_stdio(false); cin >> n >> m; for(int i = 1;i <= n;i++) { cin >> a[i]; a[i] = " "+a[i]; } for(int i = 1;i <= n;i++) { for(int j = 1;j <= m;j++) { if(a[i][j] == 'S') x1 = i,Y1 = j; } } dfs(x1,Y1,-1,-1); if(flag) cout << "YES" << endl; else cout << "NO" << endl; return 0; }
C.遍历每只老鼠,一次次缩小时间区间,最后考虑可能性,注意速率为0和边缘情况。
#include<bits/stdc++.h> #define MOD 1000000007 using namespace std; int n,flag = 0; double ansl = 0,ansr = 1e9; void f(int x,int v,int l,int r) { if(v == 0 && (x <= l || x >= r)) { flag = 1; return; } double t = 1.0*(l-x)/v,tt = 1.0*(r-x)/v; ansl = max(ansl,min(t,tt)); ansr = min(ansr,max(t,tt)); } int main() { ios::sync_with_stdio(false); cin >> n; int x1,y1,x2,y2; cin >> x1 >> y1 >> x2 >> y2; for(int i = 1;i <= n;i++) { int a,b,c,d; cin >> a >> b >> c >> d; f(a,c,x1,x2); f(b,d,y1,y2); } if(flag == 0 && ansl < ansr) cout << fixed << setprecision(10) << ansl << endl; else cout << -1 << endl; return 0; }
D.暴力每一个起点,每次移动,更新区间,记忆化一下,dp[i][j][k][l]表示当前在i,可行区间(j,k),已经经过l个点。
#include<bits/stdc++.h> using namespace std; int n,m,k,g[85][85],dp[85][85][85][85]; int dfs(int now,int l,int r,int cnt) { int &ans = dp[now][l][r][cnt]; if(ans != -1) return ans; if(cnt == k) { ans = 0; return 0; } ans = 1e9; for(int i = l+1;i < r;i++) { if(g[now][i] == 1e9) continue; int x = l,y = r; if(now < i) x = now; else y = now; ans = min(ans,g[now][i]+dfs(i,x,y,cnt+1)); } return ans; } int main() { ios::sync_with_stdio(false); cin >> n >> k >> m; for(int i = 1;i <= n;i++) { for(int j = 1;j <= n;j++) g[i][j] = 1e9; } memset(dp,-1,sizeof(dp)); for(int i = 1;i <= m;i++) { int x,y,z; cin >> x >> y >> z; g[x][y] = min(g[x][y],z); } int ans = 1e9; for(int i = 1;i <= n;i++) ans = min(ans,dfs(i,0,n+1,1)); if(ans == 1e9) cout << -1 << endl; else cout << ans << endl; return 0; }