快速荷葉葉變換
(fht.cpp/c/pas)
【問題描述】
荷葉葉是一位偉大的數♂學家。
荷葉葉發明了一個函數,並稱之爲快速荷葉葉變換(Fast H10Transfrom)
FHT(N, M) =
但荷葉葉比較懶,對於函數的計算,荷葉葉把這個任務交給了你。
由於答案可能會很大,請輸出答案對1000000007取模的值。
【輸入格式】
一行,包含兩個整數N,M。
【輸出格式】
1個整數,FHT(N,M) mod 1000000007的值。
【輸入輸出樣例】
in
3 4
out
1
【數據規模與約定】
對於 40%的數據,1 ≤N,M≤1000
對於 60%的數據,1 ≤N,M≤106
對於 100%的數據,1 ≤N,M≤109
全國信息學奧林匹克聯賽(NOIP2016)複賽 提高組 day0
第3頁共4頁
幻象
(phantom.cpp/c/pas)
【問題描述】
phantom是一位愛思考的哲♂學家。
最近phantom得到了森の妖精的真傳。在他練功的時候,每秒他的思緒中都有一定的概率浮現出奇♂異的幻象,持續x秒的幻象將產生的幻象值。
phantom練功發自真心,他想知道,在N秒內他期望產生的幻象值是多少。
【輸入格式】
第一行包含1 個正整數 N,表示總時間 N秒。
第二行包含 N個用空格隔開的在[0,100]之間的正整數,其中第i個數a[i]表示第i秒浮現幻象的概率爲百分之a[i]。
【輸出格式】
1個實數,四捨五入後保留一位小數,表示期望幻象值。
【輸入輸出樣例】
in
3
50 50 50
out
2.8
【數據規模與約定】
對於 40%的數據 N ≤ 10
對於 60%的數據 N ≤ 100
對於 100%的數據,N ≤ 106
數據規模較大,請使用效率較高的讀入方式。
全國信息學奧林匹克聯賽(NOIP2016)複賽 提高組 day0
第4頁共4頁
樹上摩托
(sherco.cpp/c/pas)
【問題描述】
Sherco是一位經驗豐富的魔♂法師。
Sherco在第零次聖盃戰爭中取得了勝利,並取得了王之寶藏——王の樹。
他想把這棵樹砍去任意條邊,拆成若干棵新樹,並裝飾在他的摩托上,讓他的摩托更加酷炫。
但Sherco認爲,這樣生成的樹不具有美感,於是Sherco想讓每棵新樹的節點數相同。
他想知道有多少種方法分割這棵樹。
【輸入格式】
第一行一個正整數N,表示這棵樹的結點總數。
接下來N-1行,每行兩個數字X,Y表示編號爲X的結點與編號爲Y的結點相連。結點編號的範圍爲[1,N]。
【輸出格式】
一個整數,表示方案數。注意,不砍去任何一條邊也算作一種方案。
【輸入輸出樣例】
in
6
1 2
2 3
2 4
4 5
5 6
out
3
【數據規模與約定】
對於40%的數據,N ≤ 15
對於60%的數據,N ≤ 105
對於100%的數據,N ≤ 106
數據規模非常大,請使用高效的讀入方式。
2 beautiful
2.1 題目述
一個長度爲n 的序列,對於每個位置i 的數ai 都有一個優美值,其定義是:找到序列中最
長的一段[l, r],滿足l i r,且[l, r] 中位數爲ai(我們比較序列中兩個位置的數的大小時,
以數值爲第一關鍵字,下標爲第二關鍵字比較。這樣的話[l, r] 的長度只有可能是奇數),r - l
- 1 就是i 的優美值。
接下來有Q 個詢問,每個詢問[l, r] 表示查詢區間[l, r] 內優美值的最大值。
2.2 輸入
第一行輸入n 接下來n 個整數,代表ai 接下來Q,代表有Q 個區間接下來Q 行,每行
兩個整數l, r(l r),表示區間的左右端點
2.3 輸出
對於每個區間的詢問,輸出答案
2.4 Sample Input
8
16 19 7 8 9 11 20 16
8
3 8
1 4
2 3
1 1
5 5
1 2
2 8
7 8
2.5 Sample Output
7
3
1
3
5
3
7
3
3
T1
題意已經給了
整除分塊
移步我的博客
如果你已經會了,那麼實在是,太簡單了。。。
#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
long long n,m;
long long ans1,ans2;
int main()
{
scanf("%d%d",&n,&m);
ans1=n*n;
for (long long r,l=1; l<=n; l=r+1)
{
if (n/l!=0) r=min(n,n/(n/l)); else r=n;
ans1=(ans1-(l+r)*(r-l+1)*(n/l)/2)%mod;
}
ans2=m*m;
for (long long r,l=1; l<=m; l=r+1)
{
if (m/l!=0) r=min(m,m/(m/l)); else r=m;
ans2=(ans2-(l+r)*(r-l+1)*(m/l)/2)%mod;
}
printf("%lld",(ans1*ans2)%mod);
}
T2
題意概括:每個時刻有的概率練功(?),功力收益是連續時長的平方(?),求n時刻的功力收益期望
設爲第秒幻象的持續時間的期望.
顯然
設表示前秒的答案
時間複雜度爲
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
double f[1000005],nx[1000005],p[1000005];
int n;
int read(){
int x=0;
char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)){
x=(x<<3)+(x<<1)+(c^'0');
c=getchar();
}
return x;
}
int main(){
n=read();
int x;
for(int i=1;i<=n;i++){
x=read();
p[i]=x*1.0/100;
}
nx[1]=p[1];
f[1]=p[1];
for(int i=2;i<=n;i++){
nx[i]=(nx[i-1]+1)*p[i];
f[i]=(f[i-1]-nx[i-1]*nx[i-1]+(nx[i-1]+1)*(nx[i-1]+1))*p[i]+(1-p[i])*f[i-1];
}
printf("%.1f\n",f[n]);
}
T3
題意概括:把一棵樹平均分成相同點數相同的塊,求要消去幾條邊。
據我所知,聯通的話,一個節點要聯通,只能往上或者往下,如果說一個節點的size滿足當前要分成的點數,那麼肯定分出來,然後以這個節點爲根的子樹,就能一起往上聯通,作爲這個節點的父親的子樹,如果到了根節點剛好分完,那麼就剛好。
深搜因爲常數太大會爆,
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int head[maxn],n,m,cnt,yin[maxn],cnty,son[maxn],son1[maxn],ce;
bool p;
struct node
{
int v,nxt;
}e[maxn<<1];
inline void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].v=v;
head[u]=cnt;
}
inline void build(int u,int fa)
{
for (int i=head[u];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==fa) continue;
build(v,u);
son1[u]+=son1[v];
}
son1[u]++;
}
inline int dfs(int u,int fa,int o)
{
if(son1[u]==o) return o;
int num=0;
for (int i=head[u]; i; i=e[i].nxt)
{
int v=e[i].v;
if (v==fa) continue;
num+=dfs(v,u,o);
if(son1[u]-num==o) return son1[u];
}
return num;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<n; i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for (int i=2; i<=sqrt(n); i++)
if (n%i==0) {if (i*i==n) {cnty++; yin[cnty]=i;} else {cnty++; yin[cnty]=i; cnty++; yin[cnty]=n/i;}}
build(1,0);
int ans=0;
for (int i=1; i<=cnty; i++)
if (dfs(1,0,yin[i])==n) ans++;
if (ans==0) ans=-1;
printf("%d",ans+2);
}
由此,精簡,如果子樹可以分成每個塊,那麼所有節點能夠剛好除以因數的數量等於,那麼就可以了
# include <bits/stdc++.h>
using namespace std;
const int root=1;
const int MAXN=1e6+10;
int n,head[MAXN],size[MAXN],tot=0;
struct rec{int to,pre;}a[MAXN*2];
inline int read()
{
int X=0,w=0; char c=0;
while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
return w?-X:X;
}
void adde(int u,int v)
{
a[++tot].pre=head[u];
a[tot].to=v;
head[u]=tot;
}
void dfs1(int u,int fa)
{
size[u]=1;
for (int i=head[u];i;i=a[i].pre){
int v=a[i].to; if (v==fa) continue;
dfs1(v,u);
size[u]+=size[v];
}
}
bool check(int R)
{
int cnt=0;
for (int i=1;i<=n;i++)
if (size[i]%R==0) cnt++;
return n/R==cnt;
}
int main()
{
n=read();
int u,v;
for (int i=1;i<n;i++) {
u=read();v=read();
adde(u,v);adde(v,u);
}
dfs1(root,-1);
int ans=0;
for (int i=1;i<=sqrt(n);i++) {
if (n%i) continue;
if (check(i)) ans++;
if (i!=n/i&&check(n/i)) ans++;
}
printf("%d\n",ans);
return 0;
}
T4
題意概括:?
#include<bits/stdc++.h>
using namespace std;
int n,q;
int a[100100],num[100100],r[1000100];
int f[25][1000100];
int main()
{
// freopen("beautiful.in","r",stdin);
// freopen("beautiful.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
memset(num,0,sizeof(num));
memset(r,0x7f,sizeof(r));
r[500000]=i;f[0][i]=1;
int j=i;
while(j>1)
{
j--;
if(a[j]>a[i]) num[j]=num[j+1]-1;
else num[j]=num[j+1]+1;
r[num[j]+500000]=j;
if(num[j]==0) f[0][i]=max(f[0][i],i-j+1);
}
j=i;
while(j<n)
{
j++;
if(a[j]>=a[i]) num[j]=num[j-1]+1;
else num[j]=num[j-1]-1;
f[0][i]=max(f[0][i],j-r[num[j]+500000]+1);
}
}
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
f[i][j]=max(f[i-1][j],f[i-1][j+(1<<(i-1))]);
scanf("%d",&q);
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
int k=log(r-l+1)/log(2);
int ans=max(f[k][l],f[k][r-(1<<k)+1]);
printf("%d\n",ans);
}
// fclose(stdin);
// fclose(stdout);
return 0;
}