好久没打cf。。感觉智商已经退化到了零点,随便找了一套div2补一补。。。。B题就卡住了
http://codeforces.com/contest/894/problem/B
B题意是给一个n*m的方格,往每个格子里填1或-1,有多少种填的方法使得每行每列乘积都等于k,k已知,-1或1
n,m范围很大
第一想法,推组合数??????
感觉毫无头绪。。。
纸上画画,发现当(n+m)是奇数时,k是-1时,方案数是0
好像一点用没有。。。。
很久之后,理性的打了一个表,看出了规律
除了(n+m)是奇数时,-1和1答案不同,其余都相同
并且结果是2^((n-1)*(m-1))
并不知道咋回事。。
#include<bits/stdc++.h>
using namespace std;
int book[100][100],k;
long long n,m;
//打表
int check()
{
for(int i=1;i<=n;i++)
{
int temp=1;
for(int j=1;j<=m;j++)
{
temp*=book[i][j];
}
if(temp!=k)
return 0;
}
for(int i=1;i<=m;i++)
{
int temp=1;
for(int j=1;j<=n;j++)
{
temp*=book[j][i];
}
if(temp!=k)
return 0;
}
return 1;
}
int ans;
void dfs(int x,int y)
{
if(y==m+1)
{
y=1;
x++;
}
if(x==n+1)
{
ans+=check();
return ;
}
book[x][y]=1;
dfs(x,y+1);
book[x][y]=-1;
dfs(x,y+1);
}
void biao()
{
int i,j;
for(n=1;n<=5;n++)
for(m=1;m<=5;m++)
{
cout<<n<<" "<<m<<" :";
ans=0;
k=1;
dfs(1,1);
cout<<ans<<" ";
k=-1,ans=0;
dfs(1,1);
cout<<ans<<endl;
}
}
//solve
const int mo=1e9+7;
long long poww(long long a,long long b)
{
long long sum=1;
while(b)
{
if(b&1)
sum=sum*a%mo;
a=a*a%mo;
b>>=1;
}
return sum;
}
int main()
{
cin>>n>>m>>k;
long long ans=poww(2,n-1);
ans=poww(ans,m-1);
if(k==1)
cout<<ans<<endl;
else
{
if((n+m)&1)
cout<<0<<endl;
else
cout<<ans<<endl;
}
return 0;
}
又看了下C
http://codeforces.com/contest/894/problem/C
题意是有一个原序列,你知道他的每一个子区间的gcd值的总集合,构造这个原序列
完全没思路
搜了下题解,感觉智商受到了侮辱。。
B:https://www.cnblogs.com/yi-ye-zhi-qiu/p/7868954.html
每一行每一列空格留空,其余n-1行m-1列任意放,每一个放的方法都对应了一个最后一行最后一列的放的方法
C:http://blog.youkuaiyun.com/hmc0411/article/details/78581318
先判断集合所有元素的gcd是否等于集合最小值,如果不等于,无论怎么构造,原序列的所有元素的gcd值肯定是没在集合里
至于等于的话,构造方法十分巧妙
每两个给定的集合的元素,中间插一个集合最小值
#include<bits/stdc++.h>
using namespace std;
int n,a[2000];
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
int temp=a[0];
for(int i=1;i<n;i++)
temp=__gcd(temp,a[i]);
if(temp!=a[0])
{
cout<<-1<<endl;
}
else
{
cout<<n+n-1<<endl;
for(int i=0;i<n;i++)
{
cout<<a[i];
if(i==n-1)
cout<<endl;
else
cout<<" "<<a[0]<<" ";
}
}
return 0;
}