數學專場..
A : 推公式
#include <bits/stdc++.h>
using namespace std;
int t,s,q;
int main(){
cin>>t>>s>>q;
int res = 0;
while(s<t){
int x = s*q;
s = x;
res++;
}
cout<<res<<endl;
return 0;
}
B: 考慮中間那個位置亂搞一下
#include <bits/stdc++.h>
using namespace std;
map<int, int> m;
map<int, int> m2;
int a[100010];
int ans[100010];
int main(){
int n;
cin>>n;
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
m[a[i]]++;
}
int k=1;
for(int i=1; i<=n; i++){
if(m[a[i]] > 1||a[i] > n){
m[a[i]] --;
ans[i] = -1;
}
else ans[i] = a[i], m2[a[i]] = true;
}
for(int i=1; i<=n; i++){
if(ans[i] == -1){
while(k<=n&&m2[k])
k++;
ans[i] = k;
m2[k] = true;
}
}
for(int i=1; i<=n; i++)
printf("%d ", ans[i]);
return 0;
}
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<math.h>
using namespace std;
#define maxn 2000020
int flag[maxn],num[maxn];
int pal[maxn];
int gcd(int a,int b){
if(b!=0) return gcd(b,a%b);
else return a;
}
void getprime(){
fill(num,num+1+maxn,1);
num[0]=num[1]=0;
int t=0;
for(int i=2;i<=maxn;i++){
if(num[i]){
for(int j=2*i;j<=maxn;j+=i){
num[j]=0;
}
}
num[i]+=num[i-1];
}
}
bool judge(int n){
int t=0;
while(n){
pal[t++]=n%10;
n=n/10;
}
for(int i=0;i<t/2;i++){
if(pal[i]!=pal[t-1-i]) return false;
}
return true;
}
int main(){
getprime();
int m=0,c=0;
int p,q;
scanf("%d%d",&p,&q);
int lmax=-1;
for(int i=1;i<=maxn;i++){
if(judge(i)&&i!=0) c++;
if(q*num[i]<=p*c){
lmax=i;
}
}
if(lmax==-1) printf("Palindromic tree is better than splay tree\n");
else printf("%d\n",lmax);
}
D: 首先給出集合中的三種關係: 自反, 對稱,傳遞, 兩個集合等價的定義是同時具有自反對稱和傳遞性。 這裏求的是滿足傳遞和對稱性,但不是等價集合的集合個數。
首先,如果對於一個二元組 <x, y> 如果它滿足傳遞和對稱性的話 那麼可以推出<x, y> == <y, x> -> <x, x> 也就是說x, y都滿足自反性。 這樣的話,我們就可以把這個集合的元素分成若干個塊,每一個塊內都是一個滿足自反,傳遞, 對稱的這麼一個塊, 那麼我們只需要不讓所有的元素都放在集合裏面就可以了。
ok。。。 那麼首先我們熟悉一下第二類斯特林數。 string[I][j] = string[I-1][j]*j + string[I-1][j-1]; 這個是遞推公式。 string[I][j]代表I個元素分成j個集合的劃分方案。
那麼對於每一個i來說的話, f[I] 就是I個元素所能分配的個數,且集合不爲空。 f[I] = sum(string[I][k]) 1<=k<=I;
那麼對於這道題答案就不是就是C(n,i)*f[I]+1 1<=I<=n-1;
#include<iostream>
#include<fstream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<list>
#include<map>
#include<set>
#include<queue>
#include<deque>
#include<vector>
#include<functional>
#include<string>
#define INF 1000000007
#define pb push_back
#define mp make_pair
#define ll long long
#define rep(i,k) for(int i=G.start[k];i!=INF;i=G.next[i])
using namespace std;
int n;
long long st[4005][4005],f[4005];
int C[4005][4005];
void Stirling()
{
for(int i=0;i<4005;i++)
st[i][0]=st[i][1]=1;
for(int i=2;i<4005;i++)
for(int j=2;j<=i;j++)
st[i][j]=(st[i-1][j-1]+j*st[i-1][j])%INF;
for(int i=0;i<4005;i++)
for(int j=1;j<=i;j++)
f[i]=(f[i]+st[i][j])%INF;
}
void C0()
{
for(int i=0;i<4005;i++)
C[i][0]=C[i][i]=1;
for(int i=1;i<4005;i++)
for(int j=1;j<=i;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%INF;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
Stirling();
f[0]=1;
C0();
long long ans=0;
for(int i=1;i<=n-1;i++){
ans=(ans+(C[n][i]*(ll)f[i])%INF)%INF;
}
ans++;
cout<<ans<<endl;
return 0;
}
E: 2-sat判定 好題!!
看了一天還是不會做的2-sat。。。 這裏膜拜一下sjut的toosimple牛。。 順便膜拜一下代碼:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=(a);i<=(n);i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define Fast_IO ios_base::sync_with_stdio(0);cin.tie(0)
namespace SAT2 {
const int N = 410;
VI e[N];
int top,Index,scc,Instack[N],Stack[N],DFN[N],Low[N];
int Belong[N];
void init(){
rep(i, 0, N-1) e[i].clear();
}
void add_edge(int u, int v){
e[u].pb(v);
}
void tarjan(int u){
DFN[u] = Low[u] = ++Index;
Instack[u] = true;
Stack[top++] = u;
int size = e[u].size();
for(int i=0; i<size; i++) {
int v = e[u][i];
if(!DFN[v]){
tarjan(v);
Low[u] = min(Low[u], Low[v]);
}
else if(Instack[v]&&Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u]){
scc++;
while(true){
int tmp = Stack[--top];
Instack[tmp] = false;
Belong[tmp] = scc;
if(tmp == u) break;
}
}
}
void solve(int n){
scc = Index = top = 0;
memset(DFN, 0, sizeof(DFN));
for(int i=0; i<2*n; i++)
if(!DFN[i]) tarjan(i);
}
}
int l;
int n,m;
char str[400];
char s[100100];
PII e[201000];
char ret[500];
int wc, wv;
bool check(int d){
SAT2::init();
for(int i =0; i<m; i++){
SAT2::add_edge(e[i].first, e[i].second);
SAT2::add_edge(e[i].second^1, e[i].first^1);
}
for(int i=0; i<=d; i++){
if(str[ret[i] - 'a'] == 'V') SAT2::add_edge(2*i+1, 2*i);
else SAT2::add_edge(2*i, 2*i+1);
}
for(int i=0; i<n; i++){
if(wc) SAT2::add_edge(2*i, 2*i+1);
if(wv) SAT2::add_edge(2*i+1, 2*i);
}
SAT2::solve(n);
for(int i=0; i<n; i++)
if(SAT2::Belong[2*i] == SAT2::Belong[2*i+1])
return false;
return true;
}
void dfs(int d, int f){
if(d == n) {
puts(ret);
throw 0;
}
int v = 0, c= 0;
rep(i, (f?0:s[d]-'a'), l-1){
ret[d] = i+'a';
if(str[i] == 'V'){
if(v >= 2) continue;
v++;
}
else {
if(c >= 2) continue;
c++;
}
if(check(d)){
dfs(d+1, f|(i!=s[d]-'a'));
}
}
}
int main()
{
wc = 1;
wv = 1;
scanf("%s", str);
l = strlen(str);
rep(i, 0, l-1) wc &= (str[i] == 'C'), wv&=(str[i] =='V');
cin>>n>>m;
rep(i, 0, m-1){
int t1,t2;
char c1[3], c2[3];
scanf("%d %s %d %s", &t1, c1, &t2, c2);
t1--; t2--;
t1 = c1[0] == 'V'?2*t1:2*t1+1;
t2 = c2[0] == 'V'?2*t2:2*t2+1;
e[i] = mp(t1, t2);
}
scanf("%s", s);
try{
dfs(0, 0);
}
catch(int e){
return 0;
}
puts("-1");
return 0;
}