最后战绩
完成7题,I题矩阵快速幂不会,太菜了
A题 简单的加法乘法计算题
使用dp和优先队列(或者线段树)
d p [ i ] = { d p [ i − j ] , 1 ≤ j ≤ n d p [ i / m i ] , i % m i = 0 dp[i] = \left\{ \begin{aligned} dp[i-j] &,1\leq j \leq n \\ dp[i/m_i]&, i \% m_i =0 \end{aligned} \right. dp[i]={dp[i−j]dp[i/mi],1≤j≤n,i%mi=0
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
using namespace std;
const int N =5e6+10;
int y,n,m;
int p[10];
int dp[N];
int tree[N<<2];
//void add(int i, int v,int l,int r,int p){
//
//}
int main(){
scanf("%d%d%d",&y,&n,&m);
// memset(dp, -1, sizeof dp);
// memset(tree, 0x3f, sizeof tree);
priority_queue<pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > q;
for(int i=0;i<m;i++){
scanf("%d",&p[i]);
}
for(int i=1;i<=n;i++){
dp[i] = 1;
q.push({1, i});
}
for(int i=n+1;i<=y;i++){
while(!q.empty() && q.top().second <i-n)q.pop();
dp[i] = 1+ q.top().first;
for(int j=0;j<m;j++){
if(i%p[j]==0){
dp[i] = min(dp[i], 1+dp[i/p[j]]);
}
}
q.push({dp[i], i});
// cout<<dp[i]<<" ";
}
printf("%d", dp[y]);
}
F题 新取模运算
( 1 , . . . , p ) , ( p + 1 , . . . , 2 p ) , ( 2 p + 1 , . . . , 3 p ) 循环出现, d p [ i ] 表示 i ! ⊕ p , 则 d p [ j ∗ p ] = j ∗ d p [ p ] (1,...,p) ,(p+1, ... ,2p),(2p+1,...,3p)循环出现,dp[i]表示i!\oplus p ,则dp[j*p] = j * dp[p] (1,...,p),(p+1,...,2p),(2p+1,...,3p)循环出现,dp[i]表示i!⊕p,则dp[j∗p]=j∗dp[p]
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
using namespace std;
const int N =1e6+10;
int p1;
long long p[N];
long long get(long long i,long long j){
long long cur = i, ans = 1;
while(j){
if(j&1){
ans=(ans*cur)%p1;
}
j>>=1;
cur=(cur*cur)%p1;
}
return ans;
}
int main(){
int t;
cin>>t>>p1;
p[1] = 1;
for(int i=2;i<p1;i++){
p[i] = p[i-1] * i % p1;
// cout<<i<<" "<<p[i]<<endl;
}
if(p1>=1)
p[p1] = p[p1-1];
p[0] = 1;
while(t--){
long long n;
cin>>n;
long long ans = 1;
while(n){
long long b = n / p1;
int y = n%p1;
ans = get(p[p1], b)*p[y]%p1 *ans %p1;
n = b;
}
cout<<ans<<endl;
}
}
C题 排列排序问题
顺序遍历,当前数和前一个数绝对值差不等于1,则加1
#include<iostream>
#include<cstring>
#include<cmath>
#include<set>
#include<queue>
using namespace std;
const int N =1e6+10;
int p[N];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>p[i];
}
bool f = true;
int ans = 0;
int i=1;
while(i<n){
if(abs(p[i] - p[i-1])!=1){
ans++;
i++;
}else{
i++;
}
}
cout<<ans;
}
L题 Azur Lane
计算最少递减组数t,则t天之前输出-1,同时得到 p r e _ s u m 1 , . . . , p r e _ s u m i pre\_sum_1,...,pre\_sum_i pre_sum1,...,pre_sumi前缀和,遍历1到 p r e _ s u m i pre\_sum_i pre_sumi,如何当前值j不在前缀和中,则放入优先队列中,t天后面的每一次从优先队列中找最小值加上去就行了。
#include<iostream>
#include<cstring>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
using namespace std;
const int N =1e6+10;
int p[N];
int a[N], pre[N];
int dd[N];
int main(){
int m,k;
cin>>m>>k;
for(int i=0;i<m;i++){
cin>>p[i];
}
vector<int> v;
int i = 1;
while(i<m){
int t = 1;
while(i<m && p[i]<=p[i-1]){
i++;
t++;
}
v.push_back(t);
if(i<m)
{
i++;
if(i>=m){
v.push_back(1);
}
}
}
int n = v.size();
set<int> s1;
long long sum = 0;
for(int i=0;i<n;i++){
pre[i+1]+=pre[i] + v[i];
s1.insert(pre[i+1]);
sum += pre[i+1];
}
int cnt=0;
for(int i=1;i<=pre[n];i++){
if(s1.find(i)==s1.end()){
dd[cnt++] = i;
}
}
for(int i=1;i<n;i++){
cout<<-1<<" ";
}
int ct = 0;
for(int i=n;i<=m;i++){
cout<<sum<<" ";
sum+= dd[ct++];
}
}
D题 网格染色
我是这样想的,最优策略是尽可能让所有正方形染上两条边,当自己是最后让所有正方形染上两条边的人,则自己一定赢,因为另外一个人必定开始染第三条边,而后自己染四条边,让所有正方形染上两条边需要2*n是个偶数,重边算两个边,则假如第一个人选择染非重边,则第二个人也选择染非重边,第一个人选择染重边,则第二个人也选择染重边,则最后一定是第一个人开始染第三条边,也就是后手一定赢
#include<iostream>
#include<cstring>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
using namespace std;
int main(){
int n;
cin>>n;
cout<<"Kelin";
}
I题 Fujisaki讨厌数学
设 x n + x − n 为 f ( n ) , 则有 f ( n ) = k ∗ f ( n − 1 ) − f ( n − 2 ) , 设x^n+x^{-n}为f(n),则有f(n) =k*f(n-1) -f(n-2), 设xn+x−n为f(n),则有f(n)=k∗f(n−1)−f(n−2), n比较大使用快速幂,比赛结束之后才补上
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <cstring>
#include <stack>
#include <cmath>
using namespace std;
const int N=2e5+10;
long long p[2][2];
int k;
int m;
void qmi(long long n){
long long cur[2][2];
cur[0][0] = k, cur[0][1] = -1;
cur[1][0] = 1, cur[1][1] = 0;
long long ans[2][2];
ans[0][0] = 1, ans[0][1] = 0;
ans[1][0] = 0, ans[1][1] = 1;
int tmp[2][2];
while(n){
if(n&1){
// ans=(mul())
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
p[i][j] = 0;
for(int k=0;k<2;k++){
p[i][j] = ((p[i][j] + cur[i][k]*ans[k][j]%m)%m + m)%m;
}
}
}
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
ans[i][j] = p[i][j];
}
}
}
n>>=1;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
tmp[i][j] = 0;
for(int k=0;k<2;k++){
tmp[i][j] = ((tmp[i][j] + cur[i][k]*cur[k][j]%m)%m + m)%m;
}
}
}
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
cur[i][j] = tmp[i][j];
}
}
}
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
p[i][j] = ans[i][j];
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
long long n;
cin>>m>>k>>n;
if(n==0){
cout<<2;
}else{
qmi(n-1);
cout<<(p[0][0] * k%m + p[0][1]*2%m)%m<<endl;
}
}