题目链接:戳这里
King's Cake
输入描述
第一行一个整数表示测试组数:T(0<T≤1000) 。
每组数据占一行,每行两个整数 n×m(1≤n,m≤10000),表示蛋糕的大小。
输出描述
共 T 行,每行一个整数表示最多能切出的正方形蛋糕数量。
输入样例
2
2 3
2 5
输出样例
3
4
Hint
对于第一组数据,可切出一个 2×2, 两个 1\times 1×1,共 3 个。
对于第一组数据,可切出两个 2×2, 两个 1\times 1×1,共 4个。
思路:模拟切蛋糕的过程就可以
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; #define INF (1ll<<60)-1 using namespace std; int n,m,T; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); if(n>m) swap(n,m); int num=0; while(n && m){ m-=n; num++; if(n>m) swap(n,m); /// printf("%d %d\n",n,m); } printf("%d\n",num); } return 0; }
思路:
1 2 3
4 5 6
7 8 9
1. 至少经过四个点,当不足四个点的时候 invalid
2. 0<si<10 不满足条件的时候 invalid
3. 处理是否经过中间数的情况 只有 1 3 7 9 或者 2 8 或者 4 6 这些情况
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; #define INF (1ll<<60)-1 using namespace std; int T,n; int a[11],vis[10]; int main(){ scanf("%d",&T); while(T--){ mst(vis,0); int flag=0; scanf("%d",&n); if(n<4) flag=1; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); if(a[i]<1 || a[i]>9) { flag=1; } } if(flag){ cout<<"invalid"<<endl; continue; } vis[a[1]]=1; for(int i=2;i<=n;i++){ if(vis[a[i]]) { flag=1; break; } if(a[i]==1 || a[i]==3 || a[i]==7 || a[i]==9){ if(a[i-1]==1 || a[i-1]==3 || a[i-1]==7 || a[i-1]==9){ if(!vis[(a[i]+a[i-1])/2]){ flag=1; break; } } } if((a[i]+a[i-1])==10 && !vis[5]){ flag=1; break; } vis[a[i]]=1; } if(flag) cout<<"invalid"<<endl; else cout<<"valid"<<endl; } return 0; }
动态规划 状态: dp[i][j] 当前长度为i 第i个字符参与进去的重复字符长度为j的种数
当前的dp[i][j]=dp[i][1] + dp[i][2] + dp[i][3] (1<=j<=3)
dp[i][1] =( dp[i-1][1] + dp[i-1][2] + dp[i-1][3] ) * 25
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; #define INF (1ll<<60)-1 #define mod 1000000007 using namespace std; int T,n; ll dp[2010][4];/// 当前长度为i 第i个字符参与进去的重复字符长度为j的种数 int main(){ dp[1][1]=26; dp[2][1]=26*25; dp[2][2]=26; dp[3][1]=26*26*25; dp[3][2]=26*25; dp[3][3]=26; for(int i=4;i<=2000;i++){ dp[i][1]=((dp[i-1][1]+dp[i-1][2]+dp[i-1][3])*25)%mod; dp[i][2]=(dp[i][2]+dp[i-1][1])%mod; dp[i][3]=(dp[i][3]+dp[i-1][2])%mod; } scanf("%d",&T); while(T--){ scanf("%d",&n); ll ans=0; for(int i=1;i<=3;i++) ans=(ans+dp[n][i])%mod; printf("%I64d\n",ans); } return 0; }
思路 :假设最后剩下的士兵编号为0 从最后一个存活的士兵编号 开始往上找上一层该士兵所处的编号是多少
设f[i] 表示当前第i轮 对于最后一个士兵在该轮所处的编号
n 剩下的编号 0 当前只剩下一个士兵 编号为 0 f[n]=0
n-1 剩下的编号 0 1 当前只剩下两个士兵 编号分别为 0 1 f[n-1] = ( f[n] + (n-1) ) % 2
n-2 剩下的编号 0 1 2 当前只剩下三个士兵 编号分别为 0 1 2 f[n-2] = ( f[n-1] + (n-2) ) % 3
.
.
.
1 剩下的编号 0 1 2 3 4 ...n-1 当前只剩下n个士兵 编号分别为 0 1 2....n-1 f[1] = ( f[2] + 1 ) % n
答案也就是 f[1] + 1
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 1000100 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; #define INF (1ll<<60)-1 using namespace std; int T,n; int dp[5010]; int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); dp[n]=0; int t=2; for(int i=n-1;i>=1;i--){ dp[i]=(dp[i+1]+i)%t; t++; } cout<<dp[1]+1<<endl; } return 0; }