D. Happy Number(solved by w222222s)
妥妥的水题,模拟一下就行了
#include
#include
using namespace std;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
char s[20];
set <long long> st;
long long cal(long long n)
{
long long ans=0;
sprintf(s,"%lld",n);
int len=strlen(s);
for(int i=0;i<len;i++)
{
ans+=(s[i]-'0')*(s[i]-'0');
}
return ans;
}
int main()
{
long long n;
scanf("%lld",&n);
long long ans=0;
int flag=0;
while(1)
{
if(n==1)
{
flag=1;
break;
}
//cout<
if(st.count(n))
break;
st.insert(n);
n=cal(n);
}
if(flag)
cout<<"HAPPY"<<endl;
else
cout<<"UNHAPPY"<<endl;
return 0;
}
F. Philosopher’s Walk (solved by practer)
是个递归,首先根据大小将位置减少到8x8,然后用打好的表判断一下。
#include
#include
#include
#include
using namespace std;
typedef long long ll;
struct node
{
int next[5];
int w[5];
node(){};
node(int a,int b,int c,int d,int e,int f,int g,int h)
{
next[1]=a;
next[2]=b;
next[3]=c;
next[4]=d;
w[1]=e;
w[2]=f;
w[3]=g;
w[4]=h;
};
};
node z[10];
int main()
{
z[1]=node(6,1,1,7,1,2,3,4);
z[2]=node(8,2,2,5,4,3,2,1);
z[3]=node(5,3,3,8,2,1,4,3);
z[4]=node(7,4,4,6,3,4,1,2);
z[6]=node(1,6,6,4,1,4,3,2);
z[5]=node(3,5,5,2,2,3,4,1);
z[7]=node(4,7,7,1,3,2,1,4);
z[8]=node(2,8,8,3,4,1,2,3);
long long n,k;
cin>>n>>k;
int flag=1;
long long x=1,y=1;
while(n>=2)
{
long long tt=(n*n/4);
int t=(k/tt+(k%tt!=0));
// cout<
int cnt=z[flag].w[t];
flag=z[flag].next[t];
n/=2;
if(cnt==1)
{
x=x;
y=y;
}
else if(cnt==2)
{
x=x;
y+=n;
}
else if(cnt==3)
{
x+=n;
y+=n;
}
else
{
x+=n;
y=y;
}
k%=(tt);
if(k==0) k=tt;
// cout<
}
cout<<x<<' '<<y<<endl;
return 0;
}
C - Game Map (solved by limn2o4)
题目赤裸裸的暗示了偏序关系,那就建图呗。
首先用利用原图的度数信息,建立从度数小的点到相邻度数大的节点的有向边,再有向图上求最长路,只要用拓扑排序就行了
#include
#define ll long long
using namespace std;
const int MAXN = 1e5 +10;
const int MAXM = 3e5 +10;
const int INF = 0x3f3f3f3f;
vector<int> e[MAXN],edge[MAXN];
int dp[MAXN],d[MAXN];
void bfs(int n)
{
for(int i = 1;i<=n;i++)
{
dp[i] = 1;
}
queue<int> q;
for(int i =1;i<=n;i++)
{
if(d[i] == 0) q.push(i);
}
while(!q.empty())
{
int u = q.front();
q.pop();
for(auto v : edge[u])
{
d[v]--;
if(d[v] == 0) q.push(v);
dp[v] = max(dp[v],dp[u]+1);
}
}
printf("%d\n",*max_element(dp+1,dp+1+n));
}
int deg[MAXN];
bool flag[MAXN];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i = 0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
u++,v++;
e[u].push_back(v);
e[v].push_back(u);
deg[u]++,deg[v]++;
}
for(int i = 1;i<=n;i++)
{
for(auto v : e[i])
{
if(deg[i] < deg[v])
{
edge[i].push_back(v);
d[v]++;
}
}
}
bfs(n);
return 0;
}
I - Slot Machines (Upsolved by limn2o4)
赛后发现自己理解有偏差,感觉很难受。
实际上这种阅读理解题是比赛的一部分吧……、
其实是求从某个位置开始的循环节,加上前面不在循环节的部分的最小值。
序列反着读,KMP一下求个最小循环节就行了
#include
#include
#define ll long long
#define next fuck
using namespace std;
const int MAXN = 1e6 + 6;
const int INF = 0x3f3f3f3f;
void kmp_pre(int x[],int m,int next[])
{
int i,j;
j = next[0] = 0;
i = 1;
while(i<=m)
{
while(0!=j && x[i] != x[j]) j = next[j];
next[++i] = ++j;
}
}
int next[MAXN];
int x[MAXN];
int main()
{
int n;
scanf("%d",&n);
for(int i = n;i>=1;i--)
{
scanf("%d",&x[i]);
}
kmp_pre(x,n,next);
int ansp = INF,ansk = INF;
for(int i = 1;i<=n;i++)
{
int np = i - next[i+1]+1,nk = n - i;
if(np + nk < ansk + ansp)
{
ansp = np,ansk = nk;
}
}
printf("%d %d\n",ansk,ansp);
return 0;
}