注意細節
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 200000+5;
int n,m,a[N],b[N],c1,c2;char s[N];
int main()
{
speed();
freopen("grade.in","r",stdin);
freopen("grade.out","w",stdout);
cin>>n>>m;
cin>>s+1;
bool flag=0;
for(int i=1;i<=n;i++)
{
if(s[i]=='.')
{
flag=1;
continue;
}
if(flag)b[++c2]=s[i]-'0';
else a[++c1]=s[i]-'0';
}
int wei=c2;
for(int i=1;i<=c2;i++)
{
if(b[i]>=5)
{
for(int j=i;j>=1;j--)
{
if(b[j]>=5)
{
wei=j-1;
b[wei]++;
m--;
if(!m)break;
}
}
break; // 一定不能忘
}
}
if(b[0])//進位
{
flag=0;
int tmp=c1;
a[tmp]++;
while(a[tmp]>=10)
{
a[tmp]-=10;
a[tmp-1]++;
tmp--;
}
}
if(a[0])cout<<a[0];//進位
for(int i=1;i<=c1;i++)cout<<a[i];
if(flag)
{
cout<<".";
for(int i=1;i<=wei;i++)cout<<b[i];
}
return 0;
}
codeforces
從一道紫題變為了黃題
我們其實只需要確定IP地址前兩部分,因為迴文,IP地址後兩部分可以確定,注意IP地址長度大於4小於12,然後就是搜尋了,還要注意每個數都至少出現過一次
遍歷前三部分比較方便,而且複雜度可以接受,所以就是\(O(255^3)\)
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 15;
int n,acc[N],used[N],tot;
vector <int> num,Ans[10005];
bool check(int x)
{
if(!x)return 1;
used[x%10]++;
return check(x/10)&&acc[x%10];
}
bool huiwen(int a,int b,int c,int d)
{
int len=num.size()-1;
// if(len>11)return 0;
for(int i=0;i<=len;i++)
{
if(num[i]!=num[len-i])return 0;
}++tot;
Ans[tot].pb(a);Ans[tot].pb(256);Ans[tot].pb(b);Ans[tot].pb(256);
Ans[tot].pb(c);Ans[tot].pb(256);Ans[tot].pb(d);
// for(int i=0;i<=len;i++)cout<<num[i]<<" ";
// cout<<endl;
return 1;
}
void del(int x)
{
if(!x)return;
used[x%10]--;
del(x/10);
}
void pushup(int x)
{
if(!x)return;
pushup(x/10);
num.pb(x%10);
}
bool hf()
{
for(int i=0;i<=9;i++)
{
// cout<<i<<" "<<used[i]<<" "<<acc[i]<<endl;
if(!used[i]&&acc[i])
{
return 0;
}
}
return 1;
}
int start(int a,int b,int c)
{
num.clear();
int tmp=0;
pushup(a/10);num.pb(a%10);
pushup(b/10);num.pb(b%10);
pushup(c/10);num.pb(c%10);
// cout<<a<<" "<<b<<" "<<c<<endl;
// for(auto v:num)cout<<v<<" ";
// cout<<endl;
int flag=0;
flag=1;
num.pb(num[0]);//最後一部分是一位數
tmp+=huiwen(a,b,c,num[0]);
if(num[1])//最後一部分是兩位數
{
if(flag==1)num.pop_back();
num.pb(num[1]);
num.pb(num[0]);
tmp+=huiwen(a,b,c,10*num[1]+num[0]);
flag=2;
}
if(num[1]*10+num[2]*100+num[0]<=255&&num[2])//最後一部分是三位數
{
if(flag==2)
{
num.pop_back();
num.pop_back();
}else if(flag==1)
{
num.pop_back();
}
num.pb(num[2]);
num.pb(num[1]);
num.pb(num[0]);
tmp+=huiwen(a,b,c,num[1]*10+num[2]*100+num[0]);
}
// int sb;
// {
// cout<<"%%"<<a<<" "<<b<<" "<<c<<endl;
// cout<<tmp<<" "<<"AC"<<endl;
// cin>>sb;
// }
return tmp;
}
int main()
{
speed();
// freopen("ipadd.in","r",stdin);
// freopen("ipadd.out","w",stdout);
cin>>n;
int a;
for(int i=1;i<=n;i++)//IP length>=4 <=12
{
cin>>a;
acc[a]=1;
}
ll ans=0;
for(int i=0;i<=255;i++)
{
used[i%10]++;//一定要考慮0的情況
if(check(i/10)&&acc[i%10])
{
for(int j=0;j<=255;j++)
{
used[j%10]++;
if(check(j/10)&&acc[j%10])
{
for(int k=0;k<=255;k++)
{
used[k%10]++;
if(check(k/10)&&acc[k%10]&&hf())
{
ans+=start(i,j,k);
}
used[k%10]--;
del(k/10);
}
}
used[j%10]--;
del(j/10);
}
}
used[i%10]--;//回溯
del(i/10);
}
cout<<ans<<endl;
for(int i=1;i<=tot;i++)//輸出方案
{
for(auto v:Ans[i])
{
if(v==256) cout<<".";
else cout<<v;
}
cout<<endl;
}
return 0;
}
C. 裝飾
水題,找規律即可
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 200000+5;
int T;
int main()
{
speed();
freopen("decorate.in","r",stdin);
freopen("decorate.out","w",stdout);
cin>>T;
ll a,b,c;
while(T--)
{
cin>>a>>b>>c;
if((a+b+c)==max({a,b,c}))
{
cout<<0<<endl;
}else
{
priority_queue <ll> q;
q.push(a);q.push(b);q.push(c);
a=q.top();q.pop();b=q.top();q.pop();c=q.top();
ll ans=0;
ans=min((b+c),(a+b+c)/3);
cout<<ans<<endl;
}
}
return 0;
}
/*
5
1 2 3
5 0 0
9 1 1
5 5 4
0 6 6
*/
D. 最大子矩陣Largest Submatrix
炸裂的暴力
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod=1e9+7;
ll n,m,ans,dp[1005][1005],a[1005][1005];char g[1005][1005],tmp[1005][1005];
int get(int i,int j)
{
if(g[i][j]=='a')return 1;//0001
if(g[i][j]=='b')return 2;//0010
if(g[i][j]=='c')return 4;//0100
if(g[i][j]=='w')return 3;//0011
if(g[i][j]=='y')return 5;//0101
if(g[i][j]=='z')return 7;//0111
if(g[i][j]=='x')return 6;//0110
}
int main()
{ //w a,b
//x b,c
//y a,c
//z a,b,c
speed();
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
while(cin>>m>>n)
{
ans=0;
for(int i=1;i<=m;i++)//w y z //w x z//x y z
{
cin>>g[i]+1;
}
for(int i=1;i<=m;i++)//w y z //w x z//x y z
{
for(int j=1;j<=n;j++)
{
a[i][j]=get(i,j);
}
}ans=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
int now=1;
for(int ii=i;ii<=m;ii++)
{
for(int jj=j;jj<=n;jj++)
{
now=a[ii][jj];
for(int iii=i;iii<=ii;iii++)
{
for(int jjj=j;jjj<=jj;jjj++)
{
now&=a[iii][jjj];
if(!now)break;
}
if(!now)break;
}
if(now)ans=max<ll>(ans,abs(ii-i+1)*(jj-j+1));
}
}
}
}
cout<<ans<<endl;
}
return 0;
}
現在想正解,我們可以貪心一下,遍歷三次,每一次,把能變為a/b/c的都變為相同的a/b/c,這樣再找最大的
如何找呢,可以用類似玉蟾宮的思想,先處理出每一列列相同元素的長,然後用棧維護,注意j-stk.top()-1這樣就不用從左往右,從右往左搜兩遍了
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod=1e9+7;
ll n,m,ans,dp[1005][1005];char g[1005][1005],tmp[1005][1005];
void find(char tg)
{
// cout<<"&&&&"<<endl;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
// cout<<tmp[i][j];
dp[i][j]=0;
if(tmp[i][j]==tg)dp[i][j]=dp[i-1][j]+1;
}
// cout<<endl;
}
stack <int> stk;
for(int i=1;i<=m;i++)
{
for(int j=0;j<=n+1;j++)
{
while(!stk.empty()&&dp[i][j]<dp[i][stk.top()])
{
int tmp=dp[i][stk.top()];//一定是最小的
stk.pop();
if(stk.empty())break;
// cout<<stk.top()<<endl;
ans=max<ll>(ans,tmp*(j-stk.top()-1));
// cout<<ans<<endl;
// stk.pop();
}
stk.push(j);
}
}
}
int main()
{ //w a,b
//x b,c
//y a,c
//z a,b,c
speed();
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
while(cin>>m>>n)
{
ans=0;
memset(g,0,sizeof g);
for(int i=1;i<=m;i++)//w y z //w x z//x y z
{
cin>>g[i]+1;
}
for(int p=1;p<=3;p++)
{
for(int x=1;x<=m;x++)
{
for(int y=1;y<=n;y++)
{
if(p==1&&(g[x][y]=='w'||g[x][y]=='y'||g[x][y]=='z'))
{
tmp[x][y]='a'-1+p;
}
else if(p==2&&(g[x][y]=='w'||g[x][y]=='x'||g[x][y]=='z'))
{
tmp[x][y]='a'-1+p;
}
else if(p==3&&(g[x][y]=='x'||g[x][y]=='y'||g[x][y]=='z'))
{
tmp[x][y]='a'-1+p;
}else
{
tmp[x][y]=g[x][y];
}
}
}
find('a'-1+p);
}
cout<<ans<<endl;
// cout<<"%%%%%%%%%"<<endl;
}
return 0;
}
E. 中國象棋
設計\(dp[i][j][k]\)有j列有1個炮,有k列有2個炮
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 105,mod=9999973;
ll n,m;ll dp[N][N][N];
ll calc(ll x)
{
return 1ll*x*(x-1)%mod/2%mod;
}
int main()
{
speed();
freopen("chess.in","r",stdin);
freopen("chess.out","w",stdout);
cin>>n>>m;
// for(int i=0;i<=m;i++)dp[0][i][m-i]=1;
dp[0][0][0]=1;
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int k=0;k<=m-j;k++)
{
dp[i][j][k]=dp[i-1][j][k]%mod;
if(k>=1)dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1)%mod;
if(k>=2)dp[i][j][k]+=dp[i-1][j+2][k-2]%mod*((j+2)*(j+1)/2)%mod;
if(j>=1)dp[i][j][k]+=dp[i-1][j-1][k]*(m-k-j+1)%mod;
if(j>=2)dp[i][j][k]+=dp[i-1][j-2][k]*calc(m-k-j+2)%mod;
if(k>=1)dp[i][j][k]+=dp[i-1][j][k-1]%mod*(m-j-k+1)%mod*j%mod;
dp[i][j][k]%=mod;
// cout<<i<<" "<<j<<" "<<k<<" "<<dp[i][j][k]<<endl;
// ans+=dp[i][j][k];
}
}
}
// ll ans=0;
for(int j=0;j<=m;j++)
for(int k=0;k<=m;k++)//這裡注意一下不是m-j
ans=(ans+dp[n][j][k])%mod;
cout<<ans<<endl;
return 0;
}
F. 奇妙的 Fibonacci
這題還是比較有思想的
首先證明\(F_i|F_j,則i|j\)
證明:\(F_i=f_{i-1}*f_2+f_{i-2}*f_1\)
\(F_i=f_{i-3}*f_2+f_{i-2}*f_3\)
同理:\(F_i=f_{i-k}*f_{k-1}+f_{i-k+1}*f_k\)
不停帶入\(k\),可推廣出\(f_{n+m}-f_{n-1}\times f_m+f_n \times f_{m+1}\)
顯然\(f_i與f_{i-1}\)互質
類比\(gcd(n+m,m)=gcd(n,m)\)
\(gcd(f_{n+m},f_m)=gcd(f_n,f_m)\)
也就是說,對於相同的\(n,m\),上述兩個同時成立\(f_i|f_j,i|j\)
設\(A_i\)為\(i\)的約數個數,\(B_i\)為\(i\)的約數平方和,\(C_i\)為\(i\)的最小質因數的冪是多少,\(D_i\)為\(i\)除去所有最小質因子後剩下的數
\(A_i\),\(B_i\)滿足互質積性
\(設q為質因子\)
\(A_q=2,B_q=1+q^2,C_q=1,D_q=1\)
當\(gcd(i,q)=1,A_{iq}=A_i*A_q,B_{iq}=B_i*B_q,C_{iq}=1,D_{iq}=i\)
當\(i|q,A_{iq}=A_i/(C_i+1)*(C_i+2),B_{iq}=B_i*q^2+B_{D_i},C_{iq}=C_i+1,D_{iq}=D_i\)
注意\(f_2\)是所有\(f_i\)的約數,要特判
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e7+5,MAX = 1e7,mod=1e9+7;
ll A[N],B[N],C[N],D[N],pr[N],tot,n,q[N],c;bool vis[N];
void get()
{
A[1]=1;B[1]=1;
for(int i=2;i<=MAX;i++)
{
// cout<<i<<endl;
if(!vis[i])
{
pr[++tot]=i;
A[i]=2;
B[i]=(1ll*i*i%mod+1)%mod;//(i*i是int必須加longlong)
C[i]=1;
D[i]=1;
}
for(int j=1;j<=tot;j++)
{
// cout<<j<<endl;
ll num=pr[j]*i;
if(num>MAX)break;
vis[num]=1;
if(i%pr[j]==0)//pr[j]是i的最小質因子
{
A[num]=A[i]/(C[i]+1)*(C[i]+2);
C[num]=C[i]+1;D[num]=D[i];
B[num]=(B[i]*1ll*(pr[j]%mod*pr[j])%mod+B[D[i]]%mod)%mod;
break;
}
else//pr[j]變成了i*pr[j]的最小質因子 ,因為i的最小質因子還沒有遍歷到
{
C[num]=1;
B[num]=(B[i]*(pr[j]%mod*pr[j])%mod+B[i]%mod)%mod;
//B[num]=B[i]*B[pr[j]]%mod;
A[num]=A[i]*A[pr[j]]%mod;
D[num]=i;
}
}
}
}
int main()
{
speed();
freopen("fibo.in","r",stdin);
freopen("fibo.out","w",stdout);
cin>>n;
get();
ll Q1,a,b;
cin>>Q1>>a>>b>>c;
q[1]=Q1;
for(int i=2;i<=n;i++)
{
q[i]=(q[i-1]*a%c+b%c)%c+1;
// cout<<q[i]<<endl;
}
ll A1=0,A2=0;
for(int i=1;i<=n;i++)
{
A1+=A[q[i]]+(q[i]&1);
A2=(A2+B[q[i]]+4*(q[i]&1))%mod;
A1%=mod;A2%=mod;
}
cout<<A1<<endl<<A2<<endl;
return 0;
}