F
题意:给定一个nn的矩阵,你可以用若干个L型物体来拼好(L型物体,长3宽1),并且特殊要求为,矩阵的左上角22的区域不能放置物体。假设方格编号是(i-1)*n+j,那么输出每个你所用到的L型物体所在的四个方格。
思路:最小的能构成的单元块是两个L拼在一起,构成一个2*4的矩形,那么最优方案就是前两行用这个单元块来横向拼凑,然后接下来的n-2行也用这个单元块来纵向拼凑。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+100;
int a[N];
signed main()
{
int n;
cin>>n;
if((n-2)%4!=0)
{
cout<<-1<<endl;
return 0;
}
cout<<(n*n-2)/4<<endl;
for(int i=3;i<=n;i+=4)
{
cout<<i<<" "<<i+n<<" "<<i+n+1<<" "<<i+n+2<<endl;
cout<<i+1<<" "<<i+2<<" "<<i+3<<" "<<i+3+n<<endl;
}
for(int i=3;i<=n;i+=4)
{
for(int j=1;j<=n;j+=2)
{
cout<<(i-1)*n+j<<" "<<(i-1)*n+j+1<<" "<<(i-1+1)*n+j<<" "<<(i-1+2)*n+j<<endl;
cout<<(i-1+1)*n+j+1<<" "<<(i-1+2)*n+j+1<<" "<<(i-1+3)*n+j+1<<" "<<(i-1+3)*n+j<<endl;
}
}
return 0;
}
D
题意:给定n张卡牌,每张卡牌有k个标识符号,每个符号都取0,1,2的三个数中的一个。
现在定义三个并行的标识符号是好的,当且仅当这三个标识符号互不相同或者完全一致。
如果三张卡片的所有对应位置的标识符号都是good的,那么我们称这样的三张卡牌为一个SET
如果五张卡牌中有两个不同的SET,我们就称这五张卡牌为META-SET
先在给定n张卡牌和他们的每一位的标识符号,请你求出这n张卡牌可以组成多少个META-SET
思路:我们知道,一组good标识符号的组成有这样的几种:000 111 222 012等等,但是无一例外,他们的和取模于3都为0,那么如果一组卡牌能够成为SET,我们抽走其中的一张,另外的两张取模于3的余数就应该和被抽走的一张的对应标识符号是相等的。
所以我们n2暴力枚举任意两张卡牌的对应标识符号之和的取模于3的余数,然后根据这个余数来匹配。
我们假设一张卡牌能够匹配cnt对,那么一张卡牌能够满足的META-SET就是C(2,cnt)个。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000+100;
map<vector<int>,int> mp;
vector<int> v[N];
signed main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
for(int j=1,temp;j<=k;j++)
{
cin>>temp;
v[i].push_back(temp);
}
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
vector<int>temp;
for(int l=0;l<k;l++)
{
temp.push_back((6-v[i][l]-v[j][l])%3);
}
mp[temp]++;
}
}
int ans=0;
for(int i=1,cnt;i<=n;i++)
{
cnt=mp[v[i]];
ans+=(cnt*(cnt-1))/2;
}
cout<<ans;
return 0;
}