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\n",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\n",ca);
else
printf("Case %d: No\n",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\n",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("\n");
}
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\n",ca++,ans);
}
}