2018 icpc 沈阳
https://codeforces.com/gym/101955
J
签到
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<string> #include <set> #include <map> #include <queue> #include <cmath> #define ll long long #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) using namespace std; const int maxn = 5e5+5; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-')f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x*f; } char s[105]; int main(){ int T; cin>>T; int n; ll ans,a,b; int Case = 0; while(T--){ n=read(); ans = 0; fo(tt,1,n) { cin.getline(s + 1, 100); b = a = 0; if (s[1] == 'b') a = 1; if (s[1] == 'c') a = 1; if (s[1] == 'i') a = 4; if (s[1] == 'l' && s[6] == 'l')a = 8; if (s[1] == '_')a = 16; if (s[1] == 'f')a = 4; if (s[1] == 'd')a = 8; if (!a)a = 16; int len = strlen(s + 1); int bs = 1; if (s[len - 1] == ']') { for (int i = len - 2; i >= 1; i--) { if (s[i] == '[')break; b = b + (s[i] - '0') * bs; bs *= 10; } } else { b = 1; } ans += a * b; } if(ans%1024) ans = ans/1024 + 1; else ans = ans/1024; cout<<"Case #"<<++Case<<": "<<ans<<endl; } return 0; }
C
先乘一个k!,并假定前k个数是有序的
最长上升序列长度是n-1,就要把一个数字排除在外,就要把一个数字插入到其他位置
分成三种情况:前k个数里的某个数插入到后n-k个里,后n-k个数插入到前k个数里,后n-k个数插入到后n-k个数里。
分别统计,要注意相邻两个数交换的情况,只能被统计一次。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<string> #include <set> #include <map> #include <queue> #include <cmath> #define ll long long #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) using namespace std; const int maxn = 505; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-')f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x*f; } int main(){ int T; T=read(); ll n,k,mod; ll ans,a,b; int Case = 0; while(T--){ n=read(); k=read(); mod=read(); k = min(n,k); a=1; for(ll i = 1;i <= k;i++){ a*=i; a%=mod; } b=(n-1)*(n-k)+1; b%=mod; ans = (a*b)%mod; cout<<"Case #"<<++Case<<": "<<ans<<endl; } return 0; }
G
圆上的整数点数量是相当有限的,对于这个题来说,询问的半径是固定不变的,可以预处理圆上的整点,由于点的数量很小,接下来就暴力修改查询即可。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<string> #include <set> #include <map> #include <queue> #include <cmath> #define ll long long #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) using namespace std; const int maxn = 6050,maxk=1e7+5; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-')f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x*f; } const int fx[4] = {-1,1,-1,1}; const int fy[4] = {-1,-1,1,1}; vector<int> st[maxk],st2[maxk]; int n,m,flag; ll weight[maxn+10][maxn+10]; int flags[maxn+10][maxn+10]; bool judge(int y,int x){ return y>=0&&y<=maxn&&x>=0&&x<=maxn; } void add(int y,int x,ll w){ weight[y][x] = w; flags[y][x] = flag; } void del(int y,int x){ weight[y][x] = 0; flags[y][x]--; } void inc(int y,int x,ll k,ll w){ int sz = st[k].size(); int dy,dx,nowy,nowx; fo(i,0,sz-1){ dx = st[k][i]; dy = st2[k][i]; fo(j,0,3){ if(dx==0&&(j==1||j==3))continue; if(dy==0&&(j==2||j==3))continue; nowy = y + dy*fy[j]; nowx = x + dx*fx[j]; if(!judge(nowy,nowx))continue; if(flags[nowy][nowx]==flag) weight[nowy][nowx] += w; } } } ll query(int y,int x,ll k){ int sz = st[k].size(); int dy,dx,nowy,nowx; ll ans = 0; fo(i,0,sz-1){ dx = st[k][i]; dy = st2[k][i]; fo(j,0,3){ if(dx==0&&(j==1||j==3))continue; if(dy==0&&(j==2||j==3))continue; nowy = y + dy*fy[j]; nowx = x + dx*fx[j]; if(judge(nowy,nowx)){ if(flags[nowy][nowx]==flag)ans += weight[nowy][nowx]; } } } return ans; } int main(){ ios::sync_with_stdio(false); int T,Case=0; T=read(); ll lastans = 0; fo(i, 0, 6000) { fo(j, 0, 6000) { if (i * i + j * j > 1e7) break; st[i * i + j * j].push_back(i); st2[i * i + j * j].push_back(j); } } while(T--) { flag++; lastans=0; int y, x, cmd; ll k, w; cout<<"Case #"<<++Case<<":"<<endl; n = read(); m = read(); fo(i, 1, n) { y = read(); x = read(); w = read(); add(y, x, w); } fo(i, 1, m) { cmd = read(); y = read(); x = read(); y = (y + lastans) % 6000ll + 1ll; x = (x + lastans) % 6000ll + 1ll; if (cmd == 1) { w = read(); add(y, x, w); } else if (cmd == 2) { del(y, x); } else if (cmd == 3) { k = read(); w = read(); inc(y, x, k, w); } else { k = read(); cout << (lastans = query(y, x, k)) << endl; } } } return 0; }
K
首先考虑一般意义上的约瑟夫环问题,把k-1个人删去后,将k...n,0..k-2重新编号,就变成一个规模为n-1的一模一样的问题了。
考虑这个题,这次求的不是最后一个,而是第m个人把k-1删去之后,就变成了从n-1个人里找第m-1个人了。
直接递推需要一个o(m)的循环,但是题目范围说m和k总有一个很小,当k很小m很大时,我们可以让它直接顶到头而不是一项一项递推,加速递推过程。
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <set> #include <cmath> #include <queue> #include <map> #define ll long long #define ld long double #define lson rt << 1, l, m #define pi acos(-1) #define rson rt << 1 | 1, m + 1, r #define fo(i, l, r) for (long long i = l; i <= r; i++) #define fd(i, l, r) for (long long i = r; i >= l; i--) #define mem(x) memset(x, 0, sizeof(x)) #define eps 3e-11 using namespace std; const ll maxn = 40000050; const ll mod = 998244353; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-') f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x * f; } ll n, m, k; int main() { int T; T = read(); int tt = 0; while (T--) { tt++; n = read(); m = read(); k = read(); ll ans = (k - 1) % (n - m + 1); if (k == 1) { ans = m - 1; } else { fo(i, n - m + 2, n) { ans = (ans + k) % i; ll js = i - ans - 1; js /= k; js--; if (n - i - 1 < js) js = n - i - 1; if (js > 0) { i += js; ans = ans + k * js; } } } printf("Case #%d: %I64d\n", tt, ans + 1); } return 0; }
L
计算几何。
首先将外部圆与中心圆的交点求出,先看能不能取到直径,可以取到的充要条件是,存在一个交点,它的对称点没有被外部圆切去。
若不能取到直径,所有交点两两连线,去距离的最大值。
本地精度存在一些问题,long double会导致WA,只有double可以过,具体原因待探究。
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <set> #include <cmath> #include <queue> #include <map> #define ll long long #define ld double #define lson rt << 1, l, m #define pi acos(-1) #define rson rt << 1 | 1, m + 1, r #define fo(i, l, r) for (long long i = l; i <= r; i++) #define fd(i, l, r) for (long long i = r; i >= l; i--) #define mem(x) memset(x, 0, sizeof(x)) #define eps 1e-10 using namespace std; const ll maxn = 1050; const ll mod = 998244353; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-') f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x * f; } struct dat { ld v; bool isr; int p; friend bool operator<(dat a, dat b) { return a.v < b.v; } }; int cnt; ll n; ld R; ld px[maxn], py[maxn], pr[maxn], ans; ld fpx[maxn], fpy[maxn]; dat ang[maxn * 2]; dat fang[maxn * 2]; ld getang(ld a, ld b, ld c) { return acos((a * a + b * b - c * c) / (a * b + a * b)); } ld tryang(ld agl) { if (agl < 0) agl = -agl; return R * sin(agl / 2.0) * 2.0; } int main() { int T; T = read(); int tt = 0; while (T--) { tt++; cnt = 0; n = read(); R = read(); ld dis, baseAngle; fo(i, 1, n) { px[i] = read(); py[i] = read(); pr[i] = read(); dis = sqrt(px[i] * px[i] + py[i] * py[i]); baseAngle = atan2(py[i], px[i]); if (pr[i] + R < dis) { continue; } if (fabs(R - pr[i]) > dis) { continue; } ang[cnt + 1].v = baseAngle - getang(dis, R, pr[i]); ang[cnt + 2].v = baseAngle + getang(dis, R, pr[i]); if (ang[cnt + 1].v < 0) ang[cnt + 1].v += pi + pi; if (ang[cnt + 1].v >= pi + pi) ang[cnt + 1].v -= pi + pi; if (ang[cnt + 2].v < 0) ang[cnt + 2].v += pi + pi; if (ang[cnt + 2].v >= pi + pi) ang[cnt + 2].v -= pi + pi; cnt += 2; } if (cnt == 0) ans = R + R; fo(i, 1, cnt) { fpx[i] = -R * cos(ang[i].v); fpy[i] = -R * sin(ang[i].v); } ans = 0.0; fo(i, 1, cnt) { fo(j, i + 1, cnt) { ans = max(ans, tryang(ang[i].v - ang[j].v)); } } ld tx, ty; fo(i, 1, cnt) { bool ok = false; fo(j, 1, n) { if ((fpx[i] - px[j]) * (fpx[i] - px[j]) + (fpy[i] - py[j]) * (fpy[i] - py[j]) < pr[j] * pr[j]) { ok = true; break; } } if (!ok) { ans = R + R; break; } } printf("Case #%d: %.15lf\n", tt, ans); } return 0; }