做了不到两个小时就打球去了。虽然没能坚持做完,但是感觉还不错。
水题。好像就是之前看的关于一个面试题还是什么的。用尽量少的钞票来表示从1到n的值,那么想想二进制原理就知道了。所以这个水题求的是二进制的位数。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int ans=0;
while(n)
{
n/=2;
ans++;
}
printf("%d\n",ans);
}
return 0;
}
B. Scoop water
数学题。裸的catalan。求C(2n,n) - C(2n,n+1) %mod
可以用Lucas定理求,不过mod太大好像没什么优化。直接暴力求逆元也能过。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define mod 1000000007
#define maxn 20010
const long long p=mod;
long long fac[maxn];
long long Pow(long long a,long long b,long long Mod)
{
long long ans=1;
while(b)
{
if(b&1)
{
b--;
ans=(ans*a)%Mod;
}
else
{
b/=2;
a=(a*a)%Mod;
}
}
return ans;
}
void init()
{
fac[0]=1;
for(int i=1;i<maxn;i++)
fac[i]=fac[i-1]*i%p;
}
long long c(long long n,long long m)
{
if(n<m)
return 0;
long long ans=fac[n]*Pow(fac[n-m]*fac[m]%p,p-2,p)%p;
return ans;
}
long long Lucas(long long n,long long m)
{
if(m==0)
return 1;
return Lucas(n/p,m/p)*c(n%p,m%p)%p;
}
long long solve(int n)
{
long long ans=c(2*n,n)-c(2*n,n+1);
return (ans%mod+mod)%mod;
}
int main()
{
init();
int n;
while(scanf("%d",&n)!=EOF)
{
printf("%lld\n",solve(n)%mod);
}
return 0;
}
C. CX‘s dreams
标程说是最大权闭合子图。图论题,不会。
最短路。wiking大神敲的。
// wiking
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
#include<iostream>
using namespace std;
const int maxn = 10000 + 5;
const int INF = 1000000000;
typedef long long LL;
typedef pair<int,int> P;
int n,m;
struct Edge{
int from,to,dis;
}e[maxn*2];
int d[maxn];
int vis[maxn];
vector<Edge> G[maxn];
void Dij(int x){
priority_queue<P,vector<P>,greater<P> > Q;
memset(vis,0,sizeof(vis));
for(int i = 0;i <= n;i++) d[i] = INF;
Q.push(P(0,x));
while(!Q.empty()){
P p = Q.top();Q.pop();
int id = p.second;
LL dis = p.first;
if(vis[id] == 1) continue;
vis[id] = 1;
d[id] = dis;
for(int i = 0;i < G[id].size();i++){
Edge edgs = G[id][i];
int to = edgs.to;
LL der = edgs.dis;
if(d[to] > d[id] + der){
d[to] = d[id] + der;
Q.push(P(d[to],to));
}
}
}
}
int a[maxn];
int dp[maxn];
int dfs(int x){
if(dp[x] != -1) return dp[x];
if(x == 1) return dp[x] = a[x];
int Max = 0;
for(int i = 0;i < G[x].size();i++){
Edge edges = G[x][i];
int to = edges.to;
int dis = edges.dis;
if(d[to]+dis == d[x]) Max = max(Max,dfs(to));
}
return dp[x] = a[x]+Max;
}
int main(){
while(scanf("%d%d",&n,&m) != EOF){
for(int i = 0;i <= n;i++) G[i].clear();
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
}
for(int i = 0;i < m;i++){
scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].dis);
e[i+m].from = e[i].to;e[i+m].to = e[i].from;e[i+m].dis = e[i].dis;
G[e[i].from].push_back(e[i]);
G[e[i].to].push_back(e[i+m]);
}
Dij(1);
if(d[n] == INF){
printf("-1\n");
continue;
}
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(n));
}
return 0;
}
E. ZZY‘s new company
题解说是线段树+倍增法查找最近公共祖先,不会做。
判断抑或的最大值是否大于m,字典树
#include <stdio.h>
#include <string.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define NODE 3200010
#define N 100010
int n;
int v[N];
int node;
int next[NODE][2];
int end[NODE];
void add(int cur,int k)
{
memset(next[node],0,sizeof(next[node]));
end[node]=0;
next[cur][k]=node++;
}
int cal(int x)
{
int i,k,cur=0;
for(i=30;i>=0;i--)
{
k=((1<<i)&x)?0:1;
if(next[cur][k]) cur=next[cur][k];
else cur=next[cur][1-k];
}
return (x^end[cur]);
}
int main()
{
int i,j,k,x,cur;
long long ans;
long long mm;
while(~scanf("%d%lld",&n,&mm))
{
node=1;
memset(next[0],0,sizeof(next[0]));
for(i=0;i<n;i++)
{
scanf("%d",&x);
v[i]=x;
cur=0;
for(j=30;j>=0;j--)
{
k=((1<<j)&x)?1:0;
if(next[cur][k]==0) add(cur,k);
cur=next[cur][k];
}
end[cur]=x;
}
for(ans=i=0;i<n;i++) ans=MAX(ans,cal(v[i]));
if(ans>mm)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
G. Apple tree
树形依赖背包,不会。
//数论题。。。还在做。。A了再把代码粘过来吧。
好吧。。。这题过不了。。。倍数问题很简单就是(x/p)*(y/p),约数的问题,方法是对p质因数分解之后求出p的所有约数,然后对每个约数的处理同 hdu 1695 稍微有点点不同,自己改下应该就ok,==,由于基本上不会莫比乌斯反演,我改了好久也改不对,pass吧。
分组背包。小建建A了,贴个代码。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
int p[1011];
int find(int x)
{
if(p[x]!=x) return p[x]=find(p[x]);
return x;
}
int dp[1011];
int n,Wmax,k,a,b;
int P[1011],W[1011];
map<int,int>root;
vector<int>e[1011];
int main()
{
while(~scanf("%d%d%d",&n,&Wmax,&k))
{
int r=1;
root.clear();
for(int i=1;i<=n;i++) p[i]=i,e[i].clear();
for(int i=1;i<=n;i++) scanf("%d%d",&P[i],&W[i]);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&a,&b);
int A=find(a),B=find(b);
if(p[A]!=B) p[A]=B;
}
for(int i=1;i<=n;i++)
{
int x=find(i);
if(root[x]==0) root[x]=r++;
e[root[x]].push_back(i);
}
// printf("%d %d\n",e[1][0],e[1][1]);
memset(dp,0,sizeof(dp));
for(int i=1;i<r;i++)
for(int v=Wmax;v>=0;v--)
for(int j=0;j<e[i].size();j++)
{
int x=e[i][j];
if(v<W[x]) continue;
dp[v]=max(dp[v],dp[v-W[x]]+P[x]);
}
printf("%d\n",dp[Wmax]);
}
}
J. Scholarship
贪心,思维题。小建建先A了,我赛后A掉了。
// 小建建
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n;
int main()
{
scanf("%d",&n);
while(n--)
{
char s[12],s1[12];
char ans[12];
int b;
scanf("%d",&b);
if(b<0)
{
printf("0\n");
continue;
}
b++;
int l=0;
while(b)
{
s1[l++]=b%10+'0';
b/=10;
}
s1[l]='\0';
l=strlen(s1);
for(int i=0;i<l;i++)
{
s[l-1-i]=s1[i];
}
s[l]='\0';
//printf("%s z\n",s);
if(l==1)
{
printf("%s\n",s);
}
else
{
while(1)
{
int tag=-1;
for(int i=1;s[i];i++)
{
if(s[i]!='0'&&s[i]==s[i-1])
{
tag=i;break;
}
}
if(tag==-1)
{
printf("%s\n",s);
break;
}
int r,a=1;
for(int i=tag+1;s[i];i++) s[i]='0';
for(int i=tag;i>=0;i--)
{
a+=s[i]-'0';
if(a<=9)
{
r=0;
s[i]=a+'0';break;
}
else
{
r=1;
s[i]=a%10+'0';
a/=10;
}
}
if(r)
{
ans[0]='1';
for(int i=0;s[i];i++)
ans[i+1]=s[i];
ans[l+1]='\0';
}
else
{
for(int i=0;s[i];i++) ans[i]=s[i];
ans[l]='\0';
}
strcpy(s,ans);
}
}
}
return 0;
}
// mine
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <strstream>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int i;
string s="";
int num;
cin>>num;
if(num<0)
{
printf("0\n");
continue;
}
if(num==0)
{
printf("1\n");
continue;
}
num++;
strstream ss;
ss << num;
ss >> s;
int cnt=s.size()-1;
bool pika=true;
while(pika){
int index=s.size();
for(i=1;i<s.size();i++)
{
if(s[i]==s[i-1] && s[i]!='0')
{
index=i;
break;
}
}
if(index==s.size())
{
cout<<s<<endl;
pika=false;
continue;
}
cnt=index;
int remain=1;
bool ok=false;
while(cnt>=0)
{
if(s[cnt]=='9' && remain==1)
{
if(cnt==0)
ok=true;
s[cnt]='0';
cnt--;
}
else if(remain)
{
s[cnt]++;
remain=0;
cnt--;
}
else
break;
}
for(int i=index+1;i<s.size();i++)
s[i]='0';
if(ok)
{
s="1"+s;
}
}
}
return 0;
}