D. Nothing is Impossible HDU - 6335
就是算可能性小于M的最大的集合,因为正确答案就只有一个,所以每次得到选项的数量之后就乘起来,再比较就完了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e3;
ll b[maxn];
int a;
int t,n,m;
int main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>a>>b[i];
}
ll ans=0,cnt=1;
sort(b,b+n);
for(int i=0;i<n;i++){
cnt*=b[i]+1;
if(cnt<=m) ans++;
else break;
}
cout<<ans<<endl;
}
}
E. Matrix from Arrays HDU - 6336
这道题,规律就是奇数的时候是LL的重复,偶数的时候是(2 * L) (2 * L )的重复,然后我们计算的时候就直接按照2L来计算就行了。
做法是,先预处理一个长度为2L的二维前缀和,然后来通过加减一些矩形来计算每个矩形的和。
#include<iostream>
#include<cstdio>
#include<string.h>
#define ll long long
using namespace std;
const int maxn = 1e2 + 10;
ll mp[maxn][maxn];
ll A[maxn];
ll M[maxn][maxn];
ll t, L, m, xo, yo, xl, yl, len;
ll sum(ll x, ll y) {
ll ans = (x / len)*(y / len)*mp[len][len];
ans += mp[x%len][len] * (y / len) + mp[len][y%len] * (x / len);
ans += mp[x%len][y%len];
return ans;
}
int main() {
cin >> t;
while (t--) {
memset(mp, 0, sizeof(mp));
memset(M, 0, sizeof(M));
memset(A, 0, sizeof(A));
cin >> L;
for (int i = 0; i<L; i++) {
cin >> A[i];
}
int cursor = 0;
for (int i = 0;i<100; ++i) {
for (int j = 0; j <= i; ++j) {
M[j+1][i - j+1] = A[cursor];
cursor = (cursor + 1) % L;
}
}
len = 2 * L;
for (int i = 1; i <= len; i++) {
for (int j = 1; j <= len; j++) {
mp[i][j] = M[i][j] + mp[i - 1][j] + mp[i][j - 1] - mp[i - 1][j - 1];
}
}
cin >> m;
while (m--) {
cin >> xo >> yo >> xl >> yl;
xo++; yo++; xl++; yl++;//?????????????
ll ans = sum(xl, yl) + sum(xo - 1, yo - 1) - sum(xl, yo - 1) - sum(xo - 1, yl);
cout << ans << endl;
}
}
}
J. Let Sudoku Rotate HDU - 6341
让郭教练旋转:这道题就是先写一个rotate函数,然后dfs,剪枝的话是因为这是一个数独,剪枝效率很高。(虽然这样说的,但是写起来还是好麻烦。。
#include<bits/stdc++.h>
using namespace std;
int t,val,ans;
const int maxn=20;
const int inf=0x3f3f3f3f;
int a[maxn][maxn];
int g[maxn][maxn];
bool vis[maxn];
bool isvaild(){
for(int i=0;i<16;i++){
int num=0;
for(int j=0;j<16;j++){
num+=a[i][j];
}
if(num!=val)return false;
}
for(int j=0;j<16;j++){
int num=0;
for(int i=0;i<16;i++){
num+=a[i][j];
}
if(num!=val)return false;
}
return true;
}
void rotate(int x,int y){
int i1,i2,j1,j2;
for(i1=4*x-3,j2=4*y-3;i1<=4*x;++i1,j2++){
for(j1=4*y-3,i2=4*x;j1<=4*y;++j1,i2--){
g[i1][j1]=a[i2][j2];
}
}
for(int i=4*x-3;i<=4*x;++i){
for(int j=4*y-3;j<=4*y;++j){
a[i][j]=g[i][j];
}
}
}
bool ok(int x,int y){
for(int i=4*x-3;i<=4*x;++i){
memset(vis,0,sizeof(vis));
for(int j=1;j<=y*4;++j){
if(vis[a[i][j]]) return 0;
vis[a[i][j]]=1;
}
}
for(int j=4*y-3;j<=4*y;++j){
memset(vis,0,sizeof(vis));
for(int i=1;i<=4*x;++i){
if(vis[a[i][j]]) return 0;
vis[a[i][j]]=1;
}
}
return 1;
}
void dfs(int x,int y,int tmp){
if(x>4){
if(tmp<ans)ans=tmp;
return;
}
if(tmp>=ans)return;
for(int i=0;i<4;i++){
if(i)rotate(x,y);
if(ok(x,y)){
if(y==4)dfs(x+1,1,tmp+i);
else dfs(x,y+1,tmp+i);
}
}
rotate(x,y);
}
int main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
ans=inf;
for(int i=0;i<=9;i++){
val+='0'+i;
}
for(int i=0;i<=5;i++){
val+='A'+i;
}
char ch;
for(int i=1;i<=16;i++){
for(int j=1;j<=16;j++){
cin>>ch;
a[i][j]=isdigit(ch)?ch-'0':ch-'A'+10;
}
}
dfs(1,1,0);
cout<<ans<<endl;
}
}
K. Expression in Memories HDU - 6342
这就是一个模拟,读懂范式的规则之后,注意0不可以做为前导0存在,但是可以单独出现,在判断之前先预处理一下‘?’ 当‘?’ 的前一个是0,并且0的前一个是操作符,那么此个问号就放操作符。
判断的时候注意当0存在的时候,判断后面的是不是数字,是的话就直接false,两个操作符在一起也直接false。
#include<bits/stdc++.h>
using namespace std;
string s;
int isNumber(char c){
if(c>='1'&&c<='9')return 1;
else return 0;
}
int t;
int main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>s;
int len=s.length();
int flag=0;
for(int i=0;i<len;i++){
if(s[i]=='?'){
if(s[i-1]=='0'){
if(s[i-2]=='+'||s[i-2]=='*'||i-2<0)s[i]='+';
else s[i]='1';
}else s[i]='1';
}
}
int is=0;
if(s[len-1]=='+'||s[len-1]=='*'||s[0]=='+'||s[0]=='*')flag=1;
else {
for(int i=0;i<len;i++){
if(s[i]=='+'||s[i]=='*'){
if(s[i+1]=='+'||s[i+1]=='*'){//两个符号挨在一起
flag=1;
break;
}
is=0;//遇到符号给置0
}
if(s[i]=='0'&&is==0){//说明此'0'是单独出来的0或者说是number的开头
if(s[i+1]>='0'&&s[i+1]<='9'){
flag=1;
break;
}
}
else if(s[i]>='1'&&s[i]<='9'){
is=1;
}
// if(i==1&&s[i-1]=='0'&&s[i]>='0'&&s[i]<='9')flag=1;
// else if(i>1&&s[i-1]=='0'&&(s[i-2]=='+'||s[i-2]=='*')&&s[i]>='0'&&s[i]<='9')flag=1;
// else if((s[i-1]=='+'||s[i-1]=='*')&&(s[i]=='+'||s[i]=='*'))flag=1;
}
}
if(flag==1)cout<<"IMPOSSIBLE"<<endl;
else cout<<s<<endl;
}
}
L. Graph Theory Homework HDU - 6343
这个题,我以为是1到n的所有的都要走完,结果是只用节点1 到 节点 n,所以就直接算1到n的path然后输出就行了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,n;
const int maxn = 1e5+50;
int a[maxn];
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>n;
memset(a,0,sizeof(a));
for(int i=0;i<n;i++){
cin>>a[i];
}
int ans=sqrt(abs(a[0]-a[n-1]));
cout<<ans<<endl;
}
}