https://ac.nowcoder.com/acm/contest/59007
A
假設數字n有len位
則小len的長度,每個都有九個方案。
長度和len一樣的,至少有n[0]-1種方案
n[0]n[0]n[0]...的這個方案暴力地跑一遍看看是不是小於等於n即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } char s[1000]; int len,ans; int main() { // freopen("1.in","r",stdin); scanf("%s",s+1); len=strlen(s+1); ans=len*9-9; ans++; for(int i=2;i<=len;i++) if(s[i]<s[1]) { ans--; break; } ans+=s[1]-'1'; cout<<ans; }
B
賽場上找規律找出來的,發現是n*n*k的因子數量-1。
考慮把n和k質因子分解,答案是∏(因子數量+1)
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll read() { ll x;scanf("%lld",&x);return x; } ll n,k,ans; map<int,int>o; void work() { n=read();k=read();ans=1;o.clear(); for(int i=2;i*i<=n;i++) while(n%i==0) { o[i]+=2; n=n/i; } if(n!=1) o[n]+=2; for(int i=2;i*i<=k;i++) while(k%i==0) { o[i]++; k=k/i; } if(k!=1) o[k]++; for(auto x:o) ans=ans*(x.second+1); printf("%lld\n",ans-1); } int main() { for(ll t=read();t;t--) work(); }
賽後請數論大師@chdy做了做
C
輸出RUSHB,連我個圈外人都知道
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } int main() { // freopen("1.in","r",stdin); cout<<"RUSHB"; }
D
注意到n只有8,所以暴力跑n的排列,按題意模擬即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } double ans,sum; int w0,w[110],x[110],y[110],noww,n,a[110]; double askdis(int u,int v) { return sqrt((x[u]-x[v])*(x[u]-x[v])+(y[u]-y[v])*(y[u]-y[v])); } void dfs(int d) { if(d==n+1) { sum=0;noww=w0; for(int i=1;i<=n;i++) { sum=sum+askdis(a[i],a[i-1])*noww; noww=noww+w[a[i]]; } ans=min(ans,sum); return ; } for(int i=d;i<=n;i++) { swap(a[i],a[d]); dfs(d+1); swap(a[i],a[d]); } } int main() { ans=1e18; n=read();w0=read(); for(int i=1;i<=n;i++) x[i]=read(); for(int i=1;i<=n;i++) y[i]=read(); for(int i=1;i<=n;i++) { w[i]=read(); a[i]=i; } dfs(1); printf("%.7lf",ans); }
E
注意到k只有50,m只有1000,所以mk地模擬一下即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } ll a[1010]; int k,m,c[60],mod=998244353; int main() { k=read();m=read(); for(int i=1;i<=k;i++) c[i]=read(); for(int i=1;i<=k;i++) a[i]=read(); for(int i=k+1;i<=m;i++) for(int j=1;j<=k;j++) a[i]=(a[i]+c[j]*a[i-j])%mod; cout<<a[m]; }
F
經典前綴和。考慮把+看成1,-看成-1,區間[l,r]“正負相互抵消”等價於l-1和r的前綴和相等。
所以記錄一下每個前綴和第一次出現的位置,ans=max(每個前綴和最後一次出現的位置-第一次出現的位置)
代碼方面可以用+1000000的方式把負數前綴和轉移到正數裏,然後用數組存。或者像我一樣使用map存第一次出現的位置。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } char s[1000010]; map<int,int>f; int sum,n,ans; int main() { f[0]=0; scanf("%s",s+1); n=strlen(s+1); for(int i=1;i<=n;i++) { if(s[i]=='+') sum++; else sum--; if(f.count(sum)) ans=max(ans,i-f[sum]); else f[sum]=i; } cout<<ans; }
G
問題是說給定一個對稱串,能否重新排列使得變成另一個對稱串。
那麼對稱的兩個字母必須一起行動,如果n是奇數,中間的字母不影響答案。
所以std統計一下對稱的字母的種類數,如果等於1就不能,對應着aaaaaa或者aabaa這些情況。
如果大於1就可以,此時把任意兩個不相同的字母交換一下即可。
總之,std是對的,輸出yes(話說我去cf交一下代碼不就知道對不對了)
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } int main() { // freopen("1.in","r",stdin); for(int t=read();t;t--) cout<<"YES\n"; }
H
出題人生怕不會寫,甚至把判斷凸包包含給端上來了,並且點的座標都是整數。
考慮暴力枚舉i,j,判斷如果一個在另一個裏面就連有向邊,於是會連出來一個有向無環圖。
對有向無環圖跑拓撲排序,計算深度d即可。將d排個序輸出。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } struct tnode { ll x,y; }; vector<tnode>node[110]; int n; int in(int a,int b) { ll x0=node[a][0].x; ll y0=node[a][0].y; ll x1,y1,x2,y2; for(int i=1;i<node[b].size();i++) { x1=node[b][i-1].x;y1=node[b][i-1].y; x2=node[b][i].x;y2=node[b][i].y; if((x1-x0)*(y2-y0)<=(x2-x0)*(y1-y0)) return 0; } x1=node[b][node[b].size()-1].x;y1=node[b][node[b].size()-1].y; x2=node[b][0].x;y2=node[b][0].y; if((x1-x0)*(y2-y0)<=(x2-x0)*(y1-y0)) return 0; return 1; } vector<int>e[110]; queue<int>q; int d[110],ru[110]; priority_queue<int>ans; int main() { // freopen("1.in","r",stdin); n=read(); for(int i=1;i<=n;i++) { for(int k=read();k;k--) { int x=read(); node[i].push_back({x,read()}); } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j)continue; if(in(j,i))// { ru[j]++; e[i].push_back(j); } } } for(int i=1;i<=n;i++) if(ru[i]==0) { d[i]=1; q.push(i); } while(q.size()) { int x=q.front(); q.pop(); for(auto y:e[x]) { ru[y]--; if(ru[y]==0) { d[y]=d[x]+1; q.push(y); } } } for(int i=1;i<=n;i++) if(!e[i].size()) ans.push(-d[i]); while(ans.size()) { printf("%d ",-ans.top()); ans.pop(); } }
I
計數類問題。考慮數字x在第i位的方案對答案的貢獻是pow(10,i-1)*(n-1)! *x,計算一下即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } ll n,sum,now,t,mod=1e9+7; int main() { // freopen("1.in","r",stdin); n=read(); for(int i=1;i<=n;i++) { sum=sum+read(); t=(t*10+1)%mod; } now=1; for(int i=1;i<n;i++) now=now*i%mod; cout<<t*sum%mod*now%mod; }
J
大膽模擬,注意數組要開ll,否則1e8*32會爆掉。
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll read() { ll x;scanf("%lld",&x);return x; } ll n,m,a[210][210]; struct node { ll a,b; char c; }o[210][210]; char s[100]; int main() { // freopen("1.in","r",stdin); n=read();m=read(); if(read()&1) { scanf("%s",s); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%lld%c%lldi",&o[i][j].a,&o[i][j].c,&o[i][j].b); printf("%lld%c%lldi ",o[i][j].a,o[i][j].c,o[i][j].b); } printf("\n"); } printf("%ss have\n",s); if(s[4]=='y') for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) o[i][j].a*=8,o[i][j].b*=8; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%lld%c%lldi ",o[i][j].a,o[i][j].c,o[i][j].b); printf("\n"); } printf("mouths,\n"); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%lld%c%lldi ",o[i][j].a*2,o[i][j].c,o[i][j].b*2); printf("\n"); } printf("eyes and\n"); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%lld%c%lldi ",o[i][j].a*4,o[i][j].c,o[i][j].b*4); printf("\n"); } printf("legs."); } else { scanf("%s",s); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%lld",&a[i][j]); printf("%lld ",a[i][j]); } printf("\n"); } printf("%ss have\n",s); if(s[4]=='y') for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]*=8; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%lld ",a[i][j]); printf("\n"); } printf("mouths,\n"); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%lld ",a[i][j]*2); printf("\n"); } printf("eyes and\n"); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%lld ",a[i][j]*4); printf("\n"); } printf("legs."); } }
K
注意到ai最多有log(ai)個1,所以 以i位結尾的所有區間的與最多有log(ai)種不同的數,用set維護一下以i位結尾的區間的與。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int read() { int x;scanf("%d",&x);return x; } set<int>ans[200010]; int main() { int n=read(); for(int i=1;i<=n;i++) { int x=read(); ans[i].insert(x); for(auto y:ans[i-1]) ans[i].insert(x&y); printf("%d ",ans[i].size()); } }
L
大膽dp
f[i][j][kk]表示在i行第j列花費了kk活力值能獲得的最大的祝福值。
f[i][j][kk]=max(f[i-1][j][kk],f[i][j-1][kk]);
若kk>=a[s[i][j]-'0'],可以更新
f[i][j][kk]=max(f[i][j][kk],max(f[i][j-1][kk-val]+a[val],f[i-1][j][kk-val]+a[val]));
最後輸出f[n][m][k]