比赛链接
思路分析:模拟题。
需要注意的是如果将字符串中所有数字提取出来的话,若数字长度过大,很容易溢出。建议直接确定数字在字符串中的首尾位置后遍历输出。
C o d e : Code: Code:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
using namespace std;
#define MaxN 100010
//#define MOD 998244353
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define endl '\n'
#define LL long long
#define PII pair
#define rint register int
#define ULL unsigned long long
const int MOD=1e9+7;
//int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
template<class T> inline void read(T& x){
x=0;int f=0;char ch=getchar();
while( !isdigit(ch) ) f|=( ch == '-' ) , ch=getchar();
while( isdigit(ch) ) x = ( x<<1 ) + ( x<<3 ) + ( ch^48 ) , ch=getchar();
x = f ? -x : x;
}
template<class T> inline void print(T x){
if ( x < 0 ) { putchar('-'); x = -x; }
if ( x >= 10 ) print( x / 10 );
putchar(x % 10 + '0');
}
char str[MaxN];
void solve(){
int n=strlen(str);
for(int i=0; i<n; i++){
if( isdigit(str[i]) ){
int j=i;
while( j < n && isdigit(str[j+1]) ) j++;
while( i < j && str[i] == '0' ) i++;
for(int k=i; k<=j; k++) cout<<str[k];
cout<<' ';
i=j;
}
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
while( gets(str) ){
solve();
}
return 0;
}
思路分析:结论题。
a & b < = max ( a , b ) a \& b <= \max(a,b) a&b<=max(a,b) 拓展到 n n n 个数字也是一样。
C o d e : Code: Code:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
using namespace std;
#define MaxN 1000010
//#define MOD 998244353
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define endl '\n'
#define LL long long
#define PII pair
#define rint register int
#define ULL unsigned long long
const int MOD=1e9+7;
//int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
template<class T> inline void read(T& x){
x=0;int f=0;char ch=getchar();
while( !isdigit(ch) ) f|=( ch == '-' ) , ch=getchar();
while( isdigit(ch) ) x = ( x<<1 ) + ( x<<3 ) + ( ch^48 ) , ch=getchar();
x = f ? -x : x;
}
template<class T> inline void print(T x){
if ( x < 0 ) { putchar('-'); x = -x; }
if ( x >= 10 ) print( x / 10 );
putchar(x % 10 + '0');
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while( T-- ){
int ans=-INF,n,m;
cin>>n;
for(int i=1; i<=n; i++){
cin>>m;
ans=max(ans,m);
}
cout<<ans<<endl;
}
return 0;
}
思路分析:思维题。
我们每次只能取 2 k {2}^k 2k颗石子。如果对 2 k {2}^k 2k m o d mod mod 3 3 3 的话,就是 1 , 2 , 1 , 2 , 1 , 2 , … 1 ,2,1,2,1,2,\ldots 1,2,1,2,1,2,….我们发现这个数列是以 1 , 2 1,2 1,2循环的。那么原题意就可以转化为取若干次石子,每次只能取 3 3 3颗石子和一次取 1 , 2 1,2 1,2颗石子的操作。取走最后一个石子的算赢。
如果当 n n n是 3 3 3的倍数的话,先手无法一次性取完,必然要剩下部分石子,我们设 n = 3 k 1 n=3{k_1} n=3k1,经过先手操作后的剩余石子为 3 k 1 − 3 k 2 − 1 3{k_1}-3{k_2}-1 3k1−3k2−1或者是 3 k 1 − 3 k 2 − 2 3{k_1}-3{k_2}-2 3k1−3k2−2,整理后发现对于 3 ( k 1 − k 2 ) − 2 3{(k_1-k_2)}-2 3(k1−k2)−2或者 3 ( k 1 − k 2 ) − 1 3{(k_1-k_2)-1} 3(k1−k2)−1,后手只要分别取 1 , 2 1,2 1,2颗石子,就能确保下一轮留给先手的石子个数为 3 3 3的倍数。先手依旧无法取走最后一颗石子,所以无法必胜。
当 n n n不是 3 3 3的倍数,先手可以先取走 1 1 1颗或者 2 2 2颗,这样留给后手的石子个数就会是 3 3 3的倍数。后手无法一次性取走所有的石子,必然会剩余石子,留到下一轮。重复上述操作,可确保先手必胜。
结论: n n n是 3 3 3的倍数则后手必胜,反之则先手必胜。
C o d e : Code: Code:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
using namespace std;
#define MaxN 100010
//#define MOD 998244353
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define endl '\n'
#define LL long long
#define PII pair
#define rint register int
#define ULL unsigned long long
const int MOD=1e9+7;
//int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
template<class T> inline void read(T& x){
x=0;int f=0;char ch=getchar();
while( !isdigit(ch) ) f|=( ch == '-' ) , ch=getchar();
while( isdigit(ch) ) x = ( x<<1 ) + ( x<<3 ) + ( ch^48 ) , ch=getchar();
x = f ? -x : x;
}
template<class T> inline void print(T x){
if ( x < 0 ) { putchar('-'); x = -x; }
if ( x >= 10 ) print( x / 10 );
putchar(x % 10 + '0');
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while( T-- ){
LL n;
cin>>n;
if( n%3 ) cout<<"Alan"<<endl;
else cout<<"Frame"<<endl;
}
return 0;
}
思路分析:线性 d p dp dp
题意很像线性 d p dp dp中的经典例题最短编辑距离,都是给定一个字符串和几种操作方案,问最少经过多少次操作,可变成要求的字符串。
那么考虑 d p dp dp做法。
设 d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1]分别为前 i i i位全 0 0 0和全 1 1 1的最少操作次数。
如果当前 A [ i ] = = 0 A[i]==0 A[i]==0的话,显然有 d p [ i ] [ 0 ] = m i n ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] + 1 ) dp[i][0]=min(dp[i-1][0],dp[i-1][1]+1) dp[i][0]=min(dp[i−1][0],dp[i−1][1]+1),此处的 d p [ i − 1 ] [ 1 ] + 1 dp[i-1][1]+1 dp[i−1][1]+1意思是先将前 i − 1 i-1 i−1位翻转为 1 1 1,最后利用前缀修改操作使得前 i i i位全 0 0 0,同时显然有 d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 0 ] + 1 , d p [ i − 1 ] [ 1 ] + 1 ) dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]+1) dp[i][1]=min(dp[i−1][0]+1,dp[i−1][1]+1),两个 + 1 +1 +1分别对应前缀修改和单点修改。
同理,当前 A [ i ] = = 1 A[i]==1 A[i]==1的话,显然有 d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 0 ] + 1 , d p [ i − 1 ] [ 1 ] ) dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]) dp[i][1]=min(dp[i−1][0]+1,dp[i−1][1]),同时显然有 d p [ i ] [ 0 ] = m i n ( d p [ i − 1 ] [ 0 ] + 1 , d p [ i − 1 ] [ 1 ] + 1 ) dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1) dp[i][0]=min(dp[i−1][0]+1,dp[i−1][1]+1)。
最终答案为 d p [ n ] [ 0 ] dp[n][0] dp[n][0]。
C o d e : Code: Code:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include
using namespace std;
#define MaxN 100010
//#define MOD 998244353
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define endl '\n'
#define LL long long
#define PII pair
#define rint register int
#define ULL unsigned long long
const int MOD=1e9+7;
//int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
template<class T> inline void read(T& x){
x=0;int f=0;char ch=getchar();
while( !isdigit(ch) ) f|=( ch == '-' ) , ch=getchar();
while( isdigit(ch) ) x = ( x<<1 ) + ( x<<3 ) + ( ch^48 ) , ch=getchar();
x = f ? -x : x;
}
template<class T> inline void print(T x){
if ( x < 0 ) { putchar('-'); x = -x; }
if ( x >= 10 ) print( x / 10 );
putchar(x % 10 + '0');
}
int A[MaxN],dp[MaxN][2];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n;
cin>>n;
for(int i=1; i<=n; i++) cin>>A[i];
for(int i=1; i<=n; i++){
if( A[i] == 0 ){
dp[i][0]=min(dp[i-1][0],dp[i-1][1]+1);
dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]+1);
}
else{
dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1);
dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]);
}
}
cout<<dp[n][0];
return 0;
}