思路,枚举
开关按下两次就复原,所以一个开关只有两种情况,按下和不按下,5*5的开关,一共25个开关,一共有2^25种情况,for (int i = 0;i < 2^25;i++)进行操作,计算按下开关次数,若大于6,则跳过,否则,进行计算,判断按下后是否符合要求,符合则更新需要的最小次数,否则不更新。最后,如果最小次数大于6输出-1,否则输出最小次数。
考虑,第一行开关状态固定,能够影响到第一行的只有第二行,其他行无法影响第一行,所以,对于第一行中的第k列,如果第k列是不亮的,为了使该灯变亮,需要第二行的第k列按钮按下;这将确定第二行的所有开关的按下/不按的操作,第二行的灯状态将确定(如果再按下第二行的开关,第一行的第k列灯将会再次不亮);第三行的开关操作由第二行的灯的状态确定,第四行的开关操作由第三行的灯的状态确定,第五行的操作由第四行的灯的状态确定,第五行是最后一行,到达枚举的终点,如果第五行的灯都是亮的,说明当前枚举的开关操作是合理的,记录开关操作次数,否则说明当前枚举的开关操作不能使灯全部都亮,操作不满足要求, 更新需要的最少的开关的操作次数。最后,如果2^5种情况得到的最小开关操作次数大于6,则输出-1,否则输出操作次数。(根据这个可以提前判断,枚举每一种开关操作时,大于6则继续下一次操作,不更新最少开关次数)注意,要取min的,数组,则初始化为0x3f,memset,按字节填充,两倍不超int数据类型最大范围;数字,非常大的一个数,比如1<<32;。
过程如下:
枚举第一行开关的2^5种操作可能情况,确定第一行的灯的状态,更新开关操作次数times,
为了使1-4行灯是亮的,确定2-5行开关的操作,更新开关操作次数times,如果times大于6,直接进入下一种情况讨论continue;,
如果第五行的灯都是亮的,说明当前枚举的开关操作是合理的,记录开关操作次数,更行最小开关操作次数min_times
否则说明当前枚举的开关操作不能使灯全部都亮,操作不满足要求
如果min_times大于6,则输出-1,否则输出min_times。
代码如下
#include<iostream>
using namespace std;
const int N=6;
int n;
char m[N];
int led[N][N];
int copy1[N][N];
int dx[5]={-1,1,0,0,0},dy[5]={0,0,0,-1,1};
void print(int a[N][N]){
for(int i = 0;i < 5;i++){
for(int j = 0;j < 5;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
}
void copy_f(int a[N][N],int b[N][N]){
for(int i = 0;i < 5;i++)
for(int j = 0;j < 5;j++)
a[i][j]=b[i][j];
}
void change(int x,int y){
for(int i = 0;i < 5;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(nx>=0&&nx<=4&&ny>=0&&ny<=4)
if(copy1[nx][ny]==1)copy1[nx][ny]=0;
else copy1[nx][ny]=1;
}
}
void work(){
int times,min_times=1<<30; //
for(int state = 0;state < 1<<5;state++) {
times=0;
copy_f(copy1,led);//复制 ,下面的操作基于copy数组,不改变led数组
for(int i = 0;i < 5;i++)//第一行
if(state>>i &1){//开关操作
change(0,4-i);
times++;
}
for(int i = 0;i < 4;i++)//根据0-3行确定1-4行操作
for(int j = 0; j < 5;j++)
if(copy1[i][j]==0){
change(i+1,j);
times++;
}
bool flag=true;
for(int i = 0;i < 5;i++)
if(copy1[4][i]==0)
{
flag=false;
break;
}
if(flag)min_times=min(min_times,times);
}
if(min_times<=6)cout<<min_times<<endl;
else cout<<-1<<endl;
}
int main(){
cin>>n;
while(n--){
for(int i = 0;i < 5;i++){
cin>>m;
for(int j = 0;j < 5;j++)
//cout<<m[j]<<" ";
if(m[j]=='1')led[i][j]=1;
else led[i][j]=0;
}
work();
}
return 0;
}
第一个小错误:change(0,4-i);写为change(0,i);,实际上不影响。
改了半天才发现的小错误:
int nx=x+dx[i],ny=y+dy[i]; 误写为int nx=x+dx[i],ny=y+dx[i];
约数之和
数的质因数表示,约数个数之和, 约数之和,
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=9901;
int qmi(int m,int k){//logk
//m^k % mod
long long res=1;
m=m%mod;
while(k){
if(k&1)res*=m%mod;
res%=mod;
m=m*m%mod;
k>>=1;
}
return (int)res;
}
int sum(int p,int k){
if(k==0)return 1;
//if(k%2==0)return (p%mod*sum(p,k-1)+1)%mod;
if(k%2==0)return ((1+qmi(p,(k-1)/2+1))*sum(p,(k-1)/2)%mod+qmi(p,k))%mod;
return (1+qmi(p,k/2+1))*sum(p,k/2)%mod;
}
int main(){
int A,B;
cin>>A>>B;
int res=1;
for(int i = 2;i <=A;i++){
int s=0;//i^s
while(A%i==0){
s++;
A/=i;
}
//cout<<"s="<<s<<" "<<endl;
if(s)res=res*sum(i,s*B)%mod;
}
if(!A)res=0;
cout<<res<<endl;
//cout<<qmi(7,3);
return 0;
}
我的qmi模板,见5.24 基础题目_wxxka的博客-CSDN博客
#include<bits/stdc++.h>
using namespace std;
const int mod=9901;
int qmi(int a,int b){
int p = mod;
long long res = 1,ci=1;
int flag=0;
if(b==0){
res%=p;
}
else{
while(b){
if (flag==0)ci=a%p;
else
ci=(ci%p)*(ci%p)%p;
if (b&1)res=(res*(ci%p))%p;
b>>=1;
flag++;
//cout<<ci<<" "<<res<<endl;
}
}
return res;
}
int sum(int p,int k){
if(k==0)return 1;
//if(k%2==0)return (p%mod*sum(p,k-1)+1)%mod;
if(k%2==0)return ((1+qmi(p,(k-1)/2+1))*sum(p,(k-1)/2)%mod+qmi(p,k))%mod;
return (1+qmi(p,k/2+1))*sum(p,k/2)%mod;
}
int main(){
int A,B;
cin>>A>>B;
int res=1;
for(int i = 2;i <=A;i++){
int s=0;//i^s
while(A%i==0){
s++;
A/=i;
}
//cout<<"s="<<s<<" "<<endl;
if(s)res=res*sum(i,s*B)%mod;
}
if(!A)res=0;
cout<<res<<endl;
//cout<<qmi(7,3);
return 0;
}