做了三题,题目都比较暴力。
A题
题目链接:A题
题意:给你一个三阶的幻方,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。现在准备将一个三阶幻方中的一些数组抹掉(0代替),交给你来进行还原,并且希望她能够判断出究竟是不是只有一组解。
如果只有一组解,输出该三阶幻方。如果多组解,输出“Too Many”。(题目保证有解)
题解:纯暴力,枚举被抹去位置的情况,并且判重加记录就可以做出来。时间复杂度O(9!)。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0] const int MOD = 1000000007; const int N = 1e5+15; const int maxn = 450; const int letter = 130; const int INF = 15000000; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int c[20],b[20],a[20],vis[20],dis[20],sum=0; bool solve(int x,int y,int z){ return b[x]+b[y]+b[z]==15; } void dfs(int x,int f){ b[x]=f; vis[f]=1; if(x==9){ if(solve(1,2,3)&&solve(4,5,6)&&solve(7,8,9)&&solve(1,4,7)&&solve(2,5,8)&&solve(3,6,9)&&solve(1,5,9)&&solve(3,5,7)) { for(int i=1;i<=9;i++) c[i]=b[i]; sum++; } return; } if(a[x+1]) dfs(x+1,a[x+1]); else for(int i=1;i<=9;i++){ if(!vis[i]&&!dis[i]) dfs(x+1,i),vis[i]=0; } } int main(){ for(int i=1;i<=9;i++) scanf("%d",a+i),dis[a[i]]=1; dfs(0,0); if(sum==1) { for(int i=1;i<=9;i++){ if(i%3==1) printf("%d",c[i]); else printf(" %d",c[i]); if(i%3==0) printf("\n"); } } else puts("Too Many"); return 0; }
B题:
题目链接:B题
题意:(中文题简单易懂)
题解:我们注意到随着缓存区K的增大,总延迟惩罚是在减少的,再看n的的大小只有100000,直接二分可做,并且可以利用优先队列维护最大值即可。
时间复杂度O(logn*logn)
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0] const int MOD = 1000000007; const int N = 1e5+15; const int maxn = 450; const int letter = 130; const int INF = 1e17; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } LL n,ps,a[N]; bool solve(LL x){ LL sum=0,vv=1; priority_queue<LL>q; while(!q.empty()) q.pop(); for(LL i=1;i<=n;i++){ if(q.size()<x) { q.push(a[i]); } else { sum+=vv*q.top(); q.pop(); vv++; q.push(a[i]); } if(sum>ps) return 0; } while(!q.empty()){ sum+=vv*q.top(); q.pop(); vv++; if(sum>ps) return 0; } /// printf("%lld %lld\n",x,sum); return 1; } int main(){ scanf("%lld%lld",&n,&ps); for(int i=1;i<=n;i++) scanf("%lld",a+i); LL l=1,r=n; LL ans=INF; while(l<=r){ LL mid=(l+r)/2; if(solve(mid)){ ans=min(ans,mid); r=mid-1; } else { l=mid+1; } } if(ans!=INF)printf("%lld\n",ans); else puts("-1"); return 0; }
C题
题目链接:C题
题意:(中文题简单易懂)
题解:仔细分析下可以看出是完全背包,但是有一些要注意的。背包的容量应该为2*k,因为建筑值肯定要超过k的。而且注意特判下,当建筑值大于等于k的时候单独拿出来计算,因为假如我的建筑值为3k 4k的时候肯定是背包更新不到的,所以特判下。时间复杂度:O(q*n*k*m)。
代码:
#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pa pair<int,int> #define pb push_back #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) const int MOD = 1000000007; const int N = 100+15; const int maxn = 2e4 + 14; const int INF = 1e17; const int letter = 130; const double pi=acos(-1.0); const double eps=1e-10; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int tc; int n,m,k; LL a[N],b[N],dp[maxn],t; int main(){ scanf("%d",&tc); while(tc--){ LL sum=0; int flag=0; scanf("%d%d%d%lld",&n,&m,&k,&t); for(int i=1;i<=m;i++) scanf("%lld",&a[i]); for(int i=1;i<=m;i++) scanf("%lld",&b[i]); for(int i=1;i<=n;i++){ LL ans=INF; for(int j=1;j<=2*k;j++) dp[j]=INF; for(int j=1;j<=m;j++){ if(b[j]==0) continue; if(b[j]>=k) { ans=min(ans,a[j]); continue; } for(int x=b[j];x<=2*k;x++) dp[x]=min(dp[x-b[j]]+a[j],dp[x]); } for(int j=k;j<=2*k;j++) ans=min(ans,dp[j]); for(int j=1;j<=m;j++) b[j]/=t; if(ans==INF) { flag=1; break; } sum+=ans; } if(flag) puts("No Answer"); else printf("%lld\n",sum); } return 0; }