A题:https://ac.nowcoder.com/acm/contest/326/A
题解:
让我们求给出一个数能否用两个2进制数来表示(此处2进制数不包括1)
首先判断该数是否为奇数,若为奇数,则一定时NO(一定有1)
之后求将其按二进制展开,若有2个以下的位数为1且 n!=0&&n!=2 输出YES
否则输出NO
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int N=3e5+7;
const long long mod=1e9+7;
int main(){
int t;
ll n;
scanf("%d",&t);
while(t--){
int ans=0;
scanf("%lld",&n);
ll tmp=n;
if(n%2==1) {
puts("NO");
continue;
}
if(n==1||n==0) {
puts("NO");
continue;
}
while(n){
if(n%2==1) ans++;
n/=2;
}
if(ans<=2&&tmp!=2) puts("YES");
else puts("NO");
//cout<<ans<<endl;
}
return 0;
}
B题:https://ac.nowcoder.com/acm/contest/326/A
题解:
可以确立一个三维的dp
第一个维度代表单词的长度;第二个维度代表该单词最后一段连续块的长度;第三个维度代表该单词当前最后一个连续块的状态(即是元音还是辅音,1为元音,0为辅音)
我们可以很容易知道的一个转移方程是当第二维度大于1时,dp[i][j][1]=dp[i-1][j-1][1]*5 dp[i][j][0]=dp[i-1][j-1][0]*21。
之后对于最后一段连续块长度是1的时候,可以知道该块前一段最后一段连续块状态不与当前块最后一段连续段状态一样的dp值*系数的累加。 即dp[i][1][1]=*系数(j从1到最大)
dp初始值为 dp[0][0][1]=dp[0][0][0]=1。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int N=3e5+7;
const long long mod=1e9+7;
ll dp[5500][55][3];
int main(){
int t;
scanf("%d",&t);
int a,b,c;
while(t--){
scanf("%d%d%d",&c,&a,&b);
memset(dp,0,sizeof(dp));
dp[0][0][1]=1;
dp[0][0][0]=1;
ll ans=0;
for(int i=1;i<=c;i++){
for(int j=0;j<=b;j++){
dp[i][1][1]+=(dp[i-1][j][0]*5)%mod;
dp[i][1][1]%=mod;
}
ans+=dp[i][1][1];
ans%=mod;
for(int j=0;j<=a;j++){
dp[i][1][0]+=(dp[i-1][j][1]*21)%mod;
dp[i][1][0]%=mod;
}
ans+=dp[i][1][0];
ans%=mod;
for(int j=2;j<=a;j++){
dp[i][j][1]=(dp[i-1][j-1][1]*5)%mod;
dp[i][j][1]%=mod;
ans+=dp[i][j][1];
ans%=mod;
}
for(int j=2;j<=b;j++){
dp[i][j][0]=(dp[i-1][j-1][0]*21)%mod;
dp[i][j][0]%=mod;
ans+=dp[i][j][0];
ans%=mod;
}
}
/*for(int i=1;i<=c;i++){
for(int j=1;j<=b;j++){
cout<<dp[i][j][0]<<' ';
}
cout<<endl;
}
cout<<endl;*/
printf("%lld\n",ans);
}
return 0;
}
C:https://ac.nowcoder.com/acm/contest/326/C
题解:
经典的bfs题。注意x*x*x会爆long long 因此要分部取模即可
思路就是设置一个vis代表该模数有没有被使用,从输入的初始值开始查找,知道出现答案 输出次数即可
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int N=3e5+7;
const long long mod=1e9+7;
bool vis[1000];
ll a,b;
ll G(ll x){
return ((((x*x)%233)*x)%233+(x*x)%233)%233;
}
ll F(ll x){
return ((((x*x)%233)*x)%233-(x*x)%233+233)%233;
}
void bfs(){
queue<ll>q;
int ans=0;
ll tmp=G(a);
vis[tmp]=true;
q.push(tmp);
tmp=F(a);
if(!vis[tmp]){
vis[tmp]=true;
q.push(tmp);
}
while(!q.empty()){
int ti=q.size();
ans++;
while(ti--){
ll x=q.front();
q.pop();
if(x==b){
printf("%d\n",ans);
return;
}
tmp=G(x);
if(!vis[tmp]){
vis[tmp]=true;
q.push(tmp);
}
tmp=F(x);
if(!vis[tmp]){
vis[tmp]=true;
q.push(tmp);
}
}
}
puts("-1");
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(vis,false,sizeof(vis));
scanf("%lld%lld",&a,&b);
if(a==b) {
puts("0");
continue;
}
bfs();
}
return 0;
}