A. Gudako and Ritsuka
留坑
B. Call of Accepted
题意:给你一些运算,包括+-*()d,d的运算是2d6=2 和 2*6,然后输出最小值和最大值
思路:按照题意模拟即可,可以用pair来存储最小值和最大值
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<stack> #include<vector> #include<map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define _e exp(1.0) #define ll long long const ll mod = 1e9+7; const int maxn = 1e5 + 5; int len; int fst[1005]; char str[1005]; pair<int,int> add(pair<int,int>p1,pair<int,int>p2)//加法 { return make_pair(p1.first+p2.first,p1.second+p2.second); } pair<int,int> sub(pair<int,int>p1,pair<int,int>p2)//减法,小的是p1的小的减p2的大的,大的是p1的小的减p2的大的 { return make_pair(p1.first-p2.second,p1.second-p2.first); } pair<int,int> mul(pair<int,int>p1,pair<int,int>p2)//乘法简单的不可行,可以把四种情况都取出来,然后比大小放进pair里 { int t1=p1.first*p2.first; int t2=p1.first*p2.second; int t3=p1.second*p2.first; int t4=p1.second*p2.second; return make_pair(min(min(t1,t2),min(t3,t4)),max(max(t1,t2),max(t3,t4))); } pair<int,int> pp(pair<int,int>p1,pair<int,int>p2)//就是题目里的运算符d,p1是第一个数,p2是第一个数*第二个数 { return make_pair(p1.first,p1.second*p2.second); } pair<int,int> judge(int begin,int end) { int i; pair<int,int> k; for(i=begin;i<=end;i++) { if(str[i]=='+' && fst[i]==fst[begin]) { k=add(judge(begin,i-1),judge(i+1,end)); return k; } } for(i=end;i>=begin;i--) { if(str[i]=='-' && fst[i]==fst[begin]) { k=sub(judge(begin,i-1),judge(i+1,end)); return k; } } for(i=begin;i<=end;i++) { if(str[i]=='*' && fst[i]==fst[begin]) { k=mul(judge(begin,i-1),judge(i+1,end)); return k; } } for(int i=end;i>=begin;i--) { if(str[i]=='d' && fst[i]==fst[begin]) { k=pp(judge(begin,i-1),judge(i+1,end)); return k; } } if(str[begin]=='(') { for(i=begin+1;fst[i]>=fst[begin+1];i++); k=judge(begin+1,i-1); } else { int n=0; for(int i=begin;i<=end;i++) { if(!(str[i]>='0' && str[i]<='9')) break; n=n*10+str[i]-'0'; } k=make_pair(n,n); } return k; } int main() { int i; while(cin>>str) { memset(fst,0,sizeof(fst)); len=strlen(str); fst[0]=1; for(i=1;i<=len-1;i++) { if(str[i-1]=='(') fst[i]=fst[i-1]+1; else if(str[i]==')') fst[i]=fst[i-1]-1; else fst[i]=fst[i-1]; } pair<int,int> ans=judge(0,len-1); printf("%d %d ",ans.first,ans.second); } return 0; }
C. Convex Hull
留坑
D. Made In Heaven
题意:求第k短路是否大于T
思路:A*算法,启发式搜索
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<stack> #include<vector> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define _e exp(1.0) #define ll long long const int maxn=10010; const ll mod = 1e9 + 7; struct node { int to; int val; int next; }; struct node2 { int to; int g,f; bool operator<(const node2 &r) const { if(r.f==f) return r.g<g; return r.f<f; } }; node edge[maxn],edge2[maxn]; int n,m,s,t,k,cnt,cnt2,ans; int dis[1010],vis[1010],head[1010],head2[1010]; void init() { memset(head,-1,sizeof(head)); memset(head2,-1,sizeof(head2)); cnt=cnt2=1; } void addedge(int from,int to,int val) { edge[cnt].to=to; edge[cnt].val=val; edge[cnt].next=head[from]; head[from]=cnt++; } void addedge2(int from,int to,int val) { edge2[cnt2].to=to; edge2[cnt2].val=val; edge2[cnt2].next=head2[from]; head2[from]=cnt2++; } bool spfa(int s,int n,int head[],node edge[],int dist[]) { queue<int>que; int inq[1010]; for(int i=0;i<=n;i++) { dis[i]=INF; inq[i]=0; } dis[s]=0; que.push(s); inq[s]++; while(!que.empty()) { int q=que.front(); que.pop(); inq[q]--; if(inq[q]>n) return false; int k=head[q]; while(k>=0) { if(dist[edge[k].to]>dist[q]+edge[k].val) { dist[edge[k].to]=edge[k].val+dist[q]; if(!inq[edge[k].to]) { inq[edge[k].to]++; que.push(edge[k].to); } } k=edge[k].next; } } return true; } int T; bool A_star(int s,int t,int n,int k,int head[],node edge[],int dist[]) { node2 e,ne; int cnt=0; priority_queue<node2>que; if(s==t) k++; if(dis[s]==INF) return false; e.to=s; e.g=0; e.f=e.g+dis[e.to]; que.push(e); while(!que.empty()) { e=que.top(); que.pop(); if(e.to==t) cnt++; if(cnt==k) return e.g<=T; for(int i=head[e.to];i!=-1;i=edge[i].next) { ne.to=edge[i].to; ne.g=e.g+edge[i].val; ne.f=ne.g+dis[ne.to]; if(ne.g>T) continue; que.push(ne); } } return false; } int main() { while(~scanf("%d%d",&n,&m)) { scanf("%d%d%d",&s,&t,&k); scanf("%d",&T); init(); for(int i=1;i<=m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); addedge2(b,a,c); } spfa(t,n,head2,edge2,dis); if(!A_star(s,t,n,k,head,edge,dis)) puts("Whitesnake!"); else puts("yareyaredawa"); } return 0; }
E. The cake is a lie
留坑
F. Fantastic Graph
题意:
一个二分图,左边有n个点,右边有m个点,一共有k条边分别连接左右两个点,问能否取这k条边中部分边,使得所有点的度数都在l~r范围内。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<stack> #include<vector> #include<map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define _e exp(1.0) #define ll long long const ll mod = 1e9+7; const int maxn = 1e5 + 5; const int MAXN=10010; const int MAXM=40010; struct edge { int to,next,cap,flow; }edge[MAXM]; int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN]; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw=0) { edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u]; edge[tol].flow=0;head[u]=tol++; edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v]; edge[tol].flow=0;head[v]=tol++; } int sap(int start,int end,int N) { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while(dep[start]<N) { if(u==end) { int Min=INF; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) if(Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(edge[i].cap-edge[i].flow && dep[v]+1 == dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=N; for(int i=head[u];i!=-1;i=edge[i].next) if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=start ) u=edge[pre[u]^1].to; } return ans; } int S,T; vector<int>ee; void add(int u,int v,int low,int high) { addedge(u,v,high-low); if(low>0) { addedge(S, v, low); ee.push_back(tol-2); addedge(u, T, low); ee.push_back(tol-2); } } bool check() { for(int i=0;i<ee.size();i++) { int e=ee[i]; if(edge[e].flow !=edge[e].cap) return false; } return true; } int main() { int N,M,K; int ca=0; while(scanf("%d%d%d",&N,&M,&K)==3) { ee.clear(); ca++; int L,R; scanf("%d%d",&L,&R); init(); S=N+M+2; T=N+M+3; for(int i=1;i<=N;i++) add(0,i,L,R); for(int i=N+1;i<=N+M;i++) add(i, N+M+1, L, R); int u,v; while(K--) { scanf("%d%d",&u,&v); addedge(u, v+N, 1); } addedge(N+M+1, 0, INF); sap(S,T,T+1); if(check()) printf("Case %d: Yes ",ca); else printf("Case %d: No ",ca); } return 0; }
G. Spare Tire
题意:给定1<=i<=n ; 要求i与m互质,求出i*i+i的累积总和
思路:
由a的递推式可以很容易地得到ai=i*(i+1)
求所有满足条件的数不好求,我们可以用所有的减去不满足条件的,即与m不互素的数贡献的a值
根据算数基本定理将m分解,与m不互素的就是至少有其中一个因子,算所有的所以要容斥
对于每个因子积sum,会形成sum,2*sum,3*sum...[n/sum]*sum这些不互素的数,
设k=[n/sum]
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<stack> #include<vector> #include<map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define _e exp(1.0) #define ll long long const ll mod = 1e9+7; const int maxn = 1e5 + 5; ll prime[10100]; int pl=0; bool vis[10010]; ll n,m; void getprime() { for(ll i=2;i<10010;i++) { if(vis[i]==false) { prime[++pl]=i; } for(int j=1;j<pl && i*prime[j]<10010;j++) { vis[i*prime[j]]=true; if(i % prime[j]==0) break; } } } ll num[15]; int tot; void bre(ll n) { tot=0; for(int i=1;i<pl && prime[i]*prime[i]<=n;i++) { if(n%prime[i]==0) { num[tot++]=prime[i]; while(n%prime[i]==0) { n/=prime[i]; } } if(n==1) break; } if(n!=1) num[tot++]=n; } ll inv2,inv3,inv6; ll fpow(ll a,ll b) { ll ans=1; ll tmp=a%mod; while(b) { if(b&1) ans=ans*tmp%mod; tmp=tmp*tmp%mod; b/=2; } return ans; } void solve() { ll ans=0; for(int i=0;i<(1<<tot);i++) { int cnt=0; ll sum=1; for(int j=0;j<tot;j++) { if(i&(1<<j)) { cnt++; sum*=num[j]; } } ll k=n/sum; sum%=mod; ll p=(1+k)*k%mod*inv2%mod*sum%mod; ll q=k*(1+k)%mod*(2*k+1)%mod*inv6%mod*sum%mod*sum%mod; if(cnt&1) { ans-=p; if(ans<0) ans+=mod; ans-=q; if(ans<0) ans+=mod; } else { ans=(ans+p); if(ans>mod) ans-=mod; ans+=q; if(ans>mod) ans-=mod; } } printf("%lld ",ans); } int main() { getprime(); inv2=fpow(2,mod-2); inv6=fpow(6,mod-2); while(~scanf("%lld%lld",&n,&m)) { bre(m); solve(); } }
H. Hamming Weight
留坑
I. Lattice's basics in digital electronics
题意:给出一个映射关系左为ascll值,右为密码,然后给出一个16进制的数,要求先将16进制转化为2进制然后每9位通过奇偶校验判断,若前8位有奇数个1并且第9位为0则通过奇偶校验,若前8位有偶数个1且第9 位为1也通过奇偶校验。取出的串在映射中进行查找,输出对应ascll值的字符。
思路:可以用map来找取编码对应的值,网上好像也有人用字典树的,应该都可以的吧,然后奇偶校验可以用异或值来进行判断。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<stack> #include<vector> #include<map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define _e exp(1.0) #define ll long long const int maxn = 1e5 + 5; map<string,int>mp; char str[200010]; int a[1000010]; int b[1000010]; char ss[20]; int getV(char ch) { if(ch>='A' && ch<='Z') return ch-'A'+10; if(ch>='a' && ch<='z') return ch-'a'+10; else return ch-'0'; } int main() { int T; int M,N; scanf("%d",&T); while(T--) { scanf("%d%d",&M,&N); int v; mp.clear(); string sss; while(N--) { scanf("%d",&v); cin>>sss; mp[sss]=v; //将二进制与对应的ascll码对应 } scanf("%s",str); int len=strlen(str); int cnta=0; for(int i=0;i<len;i++) { int v=getV(str[i]); a[cnta++]=v/8%2; a[cnta++]=v/4%2; a[cnta++]=v/2%2; a[cnta++]=v/1%2; //十六进制转化为二进制 } int cntb=0; for(int i=0;i+9<=cnta;i+=9) { int tmp=0; for(int j=0;j<9;j++) //取异或值来验证奇偶校验 tmp^=a[i+j]; if(!tmp) continue; for(int j=0;j<8;j++) //放入b数组 b[cntb++]=a[i+j]; } string now=""; for(int i=0;i<cntb;i++) { if(M==0) break; now+=(char)(b[i]+'0'); //把b数组转换为char类型的 if(mp.count(now)) { printf("%c",mp[now]); //如果有存在的已经定义好的编码就输出 M--; if(M==0) break; now=""; } } printf(" "); } return 0; }
J. Ka Chang
留坑
K. Supreme Number
题意:输出小于等于n的超级质数,超级质数是它的任何子序列都是质数。
思路:比赛的时候一开始看成字串找了好久的bug。考虑到答案中任意一位都必须是1或质数,可知答案只可能由1、2、3、5、7构成。由于任意两个不为1的数字构成 的两位数一定可以被11整除,所以答案中除1外的数字只能出现一次;1最多出现2次,因为111可以被3整除;而2、5、7三者一定不会有两者同时出现。因此满足条件的整数不会超过四位,全部预处理出来即可。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<stack> #include<vector> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define _e exp(1.0) #define ll long long const int maxn=50; const ll mod = 1e9 + 7; int a[]={1,2,3,5,7,11,13,17,23,31,37,53,71,73,113,131,137,173,311,317}; int main() { int t; int ca=1; scanf("%d",&t); while(t--) { int ans; char str[105]; scanf("%s",str); if(strlen(str)>=5) ans=317; else { int num=0; num=atoi(str); for(int i=0;i<20;i++) { if(num>=317) { ans=317; break; } else if(num<a[i] && num<317) { ans=a[i-1]; break; } } } printf("Case #%d: %d ",ca++,ans); } }