C .Coolest Ski Route
题意:给定带边权有向图,让你找一个最长的链,满足买个点最多遍历一次。
分析:记忆化搜索即可。
代码(by 胡):
#include<bits/stdc++.h>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define P pair<int,int>
#define INF 1e18
using namespace std;
const int maxn = 200005;
vector<pair<int,int> > G[maxn];
int u[maxn],v[maxn],a[maxn],vis[maxn],d[maxn];
int dp(int x,int fa){
if(d[x]>0) return d[x];
for(auto y:G[x]){
if(y.first==fa) continue;
dp(y.first,x);
d[x]=max(d[x],d[y.first]+y.second);
}
return d[x];
}
int main(){
int n,m;
scanf("%d %d",&n,&m);
while(m--){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
G[u].push_back({v,w});
}
int ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,dp(i,-1));
}
cout<<ans<<endl;
return 0;
}
D .Down the Pyramid
题意:金字塔的每一层的位置的值=下一层的两个值之和,现在给你最倒数第二层的值a1,a2...an,问你最后一层有多少种情况,满足所有数不小于0。被简单题卡了,当时就应该换一种思路。
分析:我们假设第一个位置位b0=x,那么b1=a1-x; b2=a2-b1=a2-a1+x.. 中间给限制让所有数大于等于0,则有x<=a1; x>=a1-a2; x<=a3+a2-a1 ; x>=...。
代码(by 胡):
#include<bits/stdc++.h>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define P pair<int,int>
#define INF 1e18
using namespace std;
const int maxn = 1000005;
ll a[maxn];
int main(){
int n;
cin>>n;
ll sum=0;
ll Max,Min;
for(int i=1;i<=n;i++){
scanf("%I64d",&a[i]);
if(i==1){
Max=a[1];
Min=0;
}
sum=a[i]-sum;
if(i%2==0) Min=max(Min,-sum);
else Max=min(Max,sum);
}
if(Min>Max) return puts("0")*0;
cout<<Max-Min+1<<endl;
return 0;
}
E .Expired License
题意:给定你两个最多带5位小数的double型a,b,让你用用一对素数x y表示他们的比值。
思路:我们把a和b都乘1e5、除以gcd,再验证是否是素数即可。 注意特判1,1的情况(答案是2 2)。
代码(by 胡):
#include<bits/stdc++.h>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define P pair<int,int>
#define INF 1e18
using namespace std;
const int maxn = 20000005;
bool check[maxn];
int prime[2000005];
int tot;
void init(){
check[1]=1;
for(int i=2;i<maxn;++i) {
if(!check[i]) prime[tot++] = i;
for(int j=0;j<tot;j++){
if(i*prime[j]>maxn) break;
check[i*prime[j]] = 1;
if (i%prime[j] == 0 ) break;
}
}
}
int main(){
int t;
init();
cin>>t;
char s1[10],s2[10];
while(t--){
scanf("%s %s",s1,s2);
ll a=0;
ll b=0;
int len=strlen(s1);
int fg1=0,fg2=0;
int pos1=0,pos2=0;
for(int i=0;i<len;i++){
if(s1[i]=='.') {
pos1=1;
continue;
}
else{
a=a*10+s1[i]-'0';
if(pos1) fg1++;
}
}
len=strlen(s2);
for(int i=0;i<len;i++){
if(s2[i]=='.') {
pos2=1;
continue;
}
else{
b=b*10+s2[i]-'0';
if(pos2) fg2++;
}
}
if(fg1>fg2){
fg2=fg1-fg2;
while(fg2){
b*=10;
fg2--;
}
}else if(fg2>fg1){
fg1=fg2-fg1;
while(fg1){
a*=10;
fg1--;
}
}
ll gcd=__gcd(a,b);
a=a/gcd;
b=b/gcd;
if(a==1&&b==1){
puts("2 2");
continue;
}
if(!check[a]&&!check[b]) printf("%I64d %I64d\n",a,b);
else puts("impossible");
}
return 0;
}
F .Fighting Monsters
题意:给定N个怪兽,问是否能选处两个怪兽,使得他们相互攻击,最后活着的怪兽剩1滴血。
分析:判断是否存在相邻的Fibonacci数。
代码(by 胡):
#include<bits/stdc++.h>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define P pair<int,int>
#define INF 1e18
using namespace std;
const int maxn = 1000005;
int x[maxn];
int pos[maxn];
int a[maxn];
int main(){
a[1]=1;
a[2]=1;
for(int i=3;i<=32;i++){
a[i]=a[i-1]+a[i-2];
}
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&x[i]);
}
int a1,b1;
for(int i=1;i<=32;i++){
a1=0;
b1=0;
for(int j=1;j<=n;j++){
if(x[j]==a[i]){
a1=j;
break;
}
}
for(int j=1;j<=n;j++){
if(j==a1) continue;
if(x[j]==a[i+1]){
b1=j;
break;
}
}
if(a1&&b1){
cout<<a1<<" "<<b1<<endl;
return 0;
}
}
puts("impossible");
return 0;
}
H .Hyper Illuminati
题意:给定一个数N(<1e16),问是否存在n和s,满足1^n+2^n+3^n+...s^n=N;输出n+1,s;
思路:2^54>1e16,n的范围很小,暴力就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll ans=0,m;
int main(){
scanf("%lld",&m);
for(ll i=2;i<=54;i++) {
ans=0;
for(ll j=1;j<=m;j++){
ll tp=1;
for(ll k=1;k<=i;k++) {
if(tp>m/j) {
tp=m+1;
break;
}
tp*=j;
}
if(tp>m) break;
ans+=tp;
if(ans==m) {
printf("%lld %lld\n",i+1,j);
return 0;
}
else if(ans>=m) break;
}
}
printf("impossible\n");
return 0;
}
I .It's Time for a Montage
水题
L. Logic Puzzle
题意:扫雷,复原雷图。
思路:从左上顶点开始,如果一个点a[i][j]=1,那么a[i+1][j+1]一定是雷,然后把周围9个点都-1;最后遍历一遍,全是0就输出雷的排列,否则输出impossible。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=110;
int n,m,a[N][N],vis[N][N];
int x[9]= {1,1,1,-1,-1,-1,0,0,0};
int y[9]= {1,-1,0,1,-1,0,1,-1,0};
int main() {
scanf("%d%d",&n,&m);
for(int i=0;i<=n+1;i++)
for(int j=0;j<=m+1;j++)
scanf("%d",&a[i][j]);
for(int i=0;i<=n;i++) {
for(int j=0;j<=m;j++) {
if(a[i][j]) {
vis[i+1][j+1]=1;
for(int k=0;k<9;k++) {
if(i+1+x[k]>=0&&i+1+x[k]<=n+1&&j+1+y[k]>=0&&j+1+y[k]<=m+1)
a[i+1+x[k]][j+1+y[k]]--;
}
}
}
}
for(int i=0;i<=n+1;i++) {
for(int j=0;j<=m+1;j++)
if(a[i][j]) {
printf("impossible\n");
return 0;
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++)
if(vis[i][j]) printf("X");
else printf(".");
printf("\n");
}
return 0;
}