题目:https://www.nowcoder.com/acm/contest/142#question
A题
2生1 1生0 0消除。问要多少次。
这个题目肯定是个规律题。首先暴力一下就行了。然后就可以发现规律,012和前面消除的次数关系。
然后用dfs,进行搜索。然后要用欧拉函数,关于指数循环节了。然后预处理一下欧拉函数就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll> m;
string s;
ll ph(ll x){
ll res=x,a=x;
for(ll i=2;i*i<=x;i++){
if(a%i==0) {
res=res/i*(i-1);
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
ll poww(ll a,ll b,ll mod){
ll ans=1;
while(b){
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
ll dfs(ll i,ll mod){
if(i==0) return 0;
else if(s[i]=='0') return (dfs(i-1,mod)+1)%mod;
else if(s[i]=='2') return ((3ll*poww(2,dfs(i-1,m[mod])+1,mod)-3)%mod+mod)%mod;
else return (2*dfs(i-1,mod)+2)%mod;
}
int main(){
ll t,i=1000000007;
cin>>t;
for(;i!=1;i=m[i]){
m[i]=ph(i);
}
m[1]=1;
while(t--){
cin>>s;
s="1"+s;
int len=s.length();
printf("%lld\n",dfs(len-1,1000000007));
}
return 0;
}
F题
其实就是判断去掉中心某一块,这个图形对不对称。其实就是直接暴力一下,然后优化一点就可以了吧。
#include<bits/stdc++.h>
#define INF 1e18
#define inf 1e9
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const int _max = 2005;
char mp[_max][_max];
int main(){
IOS;
int t;
cin>>t;
while(t--){
int n,m,ret = 0;
bool k = 1;
cin>>n>>m;
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= m ; j++)
cin>>mp[i][j];
int x=n/2,y=m/2;
for(int i = 1; i <= n/2; i++) {
for(int j = 1; j <= m/2; j++) {
if((mp[i][j] != mp[i][m-j+1]) || (mp[n-i+1][j] != mp[n-i+1][m-j+1]) || (mp[i][j] != mp[n-i+1][j])){
x = min(x,i);
y = min(y,j);
}
}
}
cout<<(x-1)*(y-1)<<endl;
}
return 0;
}
G题
n个数,删m个数,使得剩下的里面众数为最大的。
可以先预处理一下,若要该数最大最少需要删多少个。然后看看是否满足要求,如果小于肯定是不可以,如果大于就OK,其他可以随便删。
#include<bits/stdc++.h>
#define INF 1e18
#define inf 1e9
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const int _max = 1e5+50;
map<int,int> mp;
int a[_max];
int main(){
int t;
cin>>t;
while(t--){
mp.clear();
int n,m,val,len = 0;
int ret = -1;
cin>>n>>m;
for(int i = 1 ; i <= n ; i++){
cin>>val;
if(!mp[val]) a[++len] = val;
mp[val]++;
}
sort(a,a+len+1);
for(int i = len ; i >= 1 ; i--){
int v = 0,p = mp[a[i]];
for(int j = 1 ; j <= len ; j++){
if(i == j) continue;
if(mp[a[j]] >= p){
v += (mp[a[j]]-p+1);
if(v > m) break;
}
}
if(v <= m){
ret = a[i];
break;
}
}
cout<<ret<<endl;
}
return 0;
}
D题
要求n的矩阵行列不相等。所以需要组合出2n个数。
从2*2开始推,然后向外扩展。发现,如果3*3时,无法保留2*2所得的结果,那么就肯定无法组合出2n个。
然后就很容易知道,是需要每次扩展2行2列。然后并且保证保留原数,就是1 1 -1 -1这样的组合。
比如
1 0
1 -1
变成
x x 1 1
x x -1 -1
1 -1 1 0
1 -1 1 -1
然后就是要想办法求出x,因为又是一个2*2。猜测为一开始的2*2矩阵,发现可以/wx(果然全靠蒙就可以了)
就得到规律了。所以我们只需要先初始化一个200*200的矩阵。然后判断一下n,如果是奇数就不可以,否则就可以喽。
#include<bits/stdc++.h>
#define PI 3.1415926
#define INF 1e18
#define inf 1e9
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const ll _max = 205;
int mp[_max][_max];
void solve(){
int n = 200;
for(int i = 1 ; i <= n ; i+=2){
mp[i][i] = 1; mp[i][i+1] = 0;
mp[i+1][i] = 1 ; mp[i+1][i+1] = -1;
int val = 1;
for(int j = 1 ; j < i ; j++){
mp[i][j] = val;
mp[i+1][j] = val;
mp[j][i] = val;
mp[j][i+1] = val;
val*=-1;
}
}
}
int main(){
solve();
int t,n;
cin>>t;
while(t--){
cin>>n;
if(n&1) cout<<"impossible"<<endl;
else{
cout<<"possible"<<endl;
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= n ; j++){
cout<<mp[i][j]<<' ';
}
cout<<endl;
}
}
}
return 0;
}
补题: